Merge "fix linespacing calculation in TextLabel" into devel/master
authorBowon Ryu <bowon.ryu@samsung.com>
Fri, 1 Apr 2022 10:04:07 +0000 (10:04 +0000)
committerGerrit Code Review <gerrit@review>
Fri, 1 Apr 2022 10:04:07 +0000 (10:04 +0000)
74 files changed:
automated-tests/src/dali-toolkit-internal/CMakeLists.txt
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Characters.cpp [new file with mode: 0755]
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.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
dali-toolkit/devel-api/focus-manager/focus-finder.cpp
dali-toolkit/devel-api/text/text-utils-devel.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/controls/web-view/web-view-impl.cpp
dali-toolkit/internal/controls/web-view/web-view-impl.h
dali-toolkit/internal/file.list
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h
dali-toolkit/internal/text/character-spacing-character-run.h [new file with mode: 0644]
dali-toolkit/internal/text/character-spacing-glyph-run.h [new file with mode: 0644]
dali-toolkit/internal/text/characters-helper-functions.cpp [new file with mode: 0644]
dali-toolkit/internal/text/characters-helper-functions.h [new file with mode: 0644]
dali-toolkit/internal/text/cursor-helper-functions.cpp
dali-toolkit/internal/text/decorator/text-decorator.cpp
dali-toolkit/internal/text/glyph-metrics-helper.cpp
dali-toolkit/internal/text/layouts/layout-engine-helper-functions.cpp
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/logical-model-impl.cpp
dali-toolkit/internal/text/logical-model-impl.h
dali-toolkit/internal/text/markup-processor-character-spacing.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor-character-spacing.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor-span.cpp
dali-toolkit/internal/text/markup-processor-span.h
dali-toolkit/internal/text/markup-processor.cpp
dali-toolkit/internal/text/markup-processor.h
dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.cpp [new file with mode: 0644]
dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h [new file with mode: 0644]
dali-toolkit/internal/text/rendering/text-typesetter.cpp
dali-toolkit/internal/text/rendering/view-model.cpp
dali-toolkit/internal/text/rendering/view-model.h
dali-toolkit/internal/text/text-controller-background-actor.cpp
dali-toolkit/internal/text/text-controller-event-handler.cpp
dali-toolkit/internal/text/text-controller-impl-model-updater.cpp
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller-text-updater.cpp
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-model-interface.h
dali-toolkit/internal/text/text-model.cpp
dali-toolkit/internal/text/text-model.h
dali-toolkit/internal/text/text-selection-handle-controller.cpp
dali-toolkit/internal/text/text-view-interface.h
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/text/text-view.h
dali-toolkit/internal/text/visual-model-impl.cpp
dali-toolkit/internal/text/visual-model-impl.h
dali-toolkit/styles/images-common/button-down.9.png
dali-toolkit/styles/images-common/button-up.9.png
dali-toolkit/styles/images-common/checkbox-selected-disabled.png
dali-toolkit/styles/images-common/checkbox-selected.png
dali-toolkit/styles/images-common/checkbox-unselected-disabled.png
dali-toolkit/styles/images-common/checkbox-unselected.png
dali-toolkit/styles/images-common/radio-button-selected-disabled.png
dali-toolkit/styles/images-common/radio-button-selected.png
dali-toolkit/styles/images-common/radio-button-unselected-disabled.png
dali-toolkit/styles/images-common/radio-button-unselected.png
packaging/dali-toolkit.spec

index 198d183..035f6c3 100755 (executable)
@@ -18,6 +18,7 @@ SET(TC_SOURCES
  utc-Dali-ItemView-internal.cpp
  utc-Dali-LogicalModel.cpp
  utc-Dali-PropertyHelper.cpp
+ utc-Dali-Text-Characters.cpp
  utc-Dali-Text-CharacterSetConversion.cpp
  utc-Dali-Text-Circular.cpp
  utc-Dali-Text-Controller.cpp
@@ -72,6 +73,7 @@ SET(TEST_HARNESS_SOURCES
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-tts-player.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-vector-image-renderer.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-window.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-scene-holder.cpp
    ../dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.cpp
index e22071a..e8bbb21 100644 (file)
@@ -116,7 +116,8 @@ void CreateTextModel(const std::string&                text,
                                       logicalModel->mUnderlinedCharacterRuns,
                                       logicalModel->mBackgroundColorRuns,
                                       logicalModel->mStrikethroughCharacterRuns,
-                                      logicalModel->mBoundedParagraphRuns);
+                                      logicalModel->mBoundedParagraphRuns,
+                                      logicalModel->mCharacterSpacingCharacterRuns);
 
   Length         textSize = 0u;
   const uint8_t* utf8     = NULL;
index c156b6e..9a3ef2b 100644 (file)
@@ -12,6 +12,7 @@
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/controls/popup/popup.h>
 #include <dali-toolkit/devel-api/controls/table-view/table-view.h>
+#include <dali-toolkit/devel-api/controls/web-view/web-view.h>
 #include <dali/devel-api/actors/actor-devel.h>
 #include <dali/devel-api/common/stage.h>
 #include <cstdlib>
@@ -1299,3 +1300,36 @@ int UtcDaliAccessibilityCheckHighlight(void)
   Dali::Accessibility::TestEnableSC( false );
   END_TEST;
 }
+
+int UtcDaliWebViewAccessible(void)
+{
+  ToolkitTestApplication application;
+
+  auto webView = Dali::Toolkit::WebView::New();
+  auto webViewAccessible = Dali::Accessibility::Accessible::Get(webView);
+
+  DALI_TEST_CHECK(webViewAccessible);
+
+  auto children = webViewAccessible->GetChildren();
+
+  DALI_TEST_CHECK(children.empty());
+
+  Dali::Accessibility::TestEnableSC(true);
+
+  children = webViewAccessible->GetChildren();
+
+  DALI_TEST_EQUALS(children.size(), 1u, TEST_LOCATION);
+
+  auto address = children[0]->GetAddress();
+
+  DALI_TEST_CHECK(address);
+  DALI_TEST_NOT_EQUALS(address.GetBus(), webViewAccessible->GetAddress().GetBus(), 0.0f, TEST_LOCATION);
+
+  Dali::Accessibility::TestEnableSC(false);
+
+  children = webViewAccessible->GetChildren();
+
+  DALI_TEST_CHECK(children.empty());
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Characters.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Characters.cpp
new file mode 100755 (executable)
index 0000000..259d682
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/internal/text/characters-helper-functions.h>
+#include <toolkit-text-utils.h>
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the following function.
+//
+//  CharacterRun RetrieveClusteredCharactersOfCharacterIndex(const VisualModelPtr&  visualModel,
+//                                                          const LogicalModelPtr& logicalModel,
+//                                                          const CharacterIndex&  characterIndex)
+
+//////////////////////////////////////////////////////////
+
+namespace
+{
+const std::string  DEFAULT_FONT_DIR("/resources/fonts");
+const unsigned int DEFAULT_FONT_SIZE = 1152u;
+
+struct RetrieveClusteredCharactersOfCharacterIndexData
+{
+  std::string     description;            ///< Description of the test.
+  std::string     text;                   ///< Input text.
+  bool            markupProcessorEnabled; //< Enable markup processor to use markup text.
+  unsigned int    numberOfTests;          ///< The number of tests.
+  CharacterIndex* characterIndex;         ///< The character index for each test.
+  CharacterRun*   clusteredCharacters;    ///< The expected clustered characters run for each test.
+};
+
+bool GetRetrieveClusteredCharactersOfCharacterIndexTest(const RetrieveClusteredCharactersOfCharacterIndexData& data)
+{
+  std::cout << "  testing : " << data.description << std::endl;
+
+  // 1) Create the model.
+  ModelPtr   textModel;
+  MetricsPtr metrics;
+  Size       textArea(400.f, 600.f);
+  Size       layoutSize;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  LayoutOptions              options;
+  CreateTextModel(data.text,
+                  textArea,
+                  fontDescriptionRuns,
+                  options,
+                  layoutSize,
+                  textModel,
+                  metrics,
+                  data.markupProcessorEnabled,
+                  LineWrap::WORD,
+                  false,
+                  Toolkit::DevelText::EllipsisPosition::END,
+                  0.0f, // lineSpacing
+                  0.0f  // characterSpacing
+  );
+
+  LogicalModelPtr logicalModel = textModel->mLogicalModel;
+  VisualModelPtr  visualModel  = textModel->mVisualModel;
+
+  for(unsigned int index = 0; index < data.numberOfTests; ++index)
+  {
+    CharacterRun clusteredCharacters = RetrieveClusteredCharactersOfCharacterIndex(visualModel, logicalModel, data.characterIndex[index]);
+
+    if(clusteredCharacters.characterIndex != data.clusteredCharacters[index].characterIndex)
+    {
+      std::cout << "  test " << index << " failed. Different clusteredCharacters.characterIndex : " << clusteredCharacters.characterIndex << ", expected : " << data.clusteredCharacters[index].characterIndex << std::endl;
+      return false;
+    }
+
+    if(clusteredCharacters.numberOfCharacters != data.clusteredCharacters[index].numberOfCharacters)
+    {
+      std::cout << "  test " << index << " failed. Different clusteredCharacters.numberOfCharacters : " << clusteredCharacters.numberOfCharacters << ", expected : " << data.clusteredCharacters[index].numberOfCharacters << std::endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+} // namespace
+
+//////////////////////////////////////////////////////////
+//
+// UtcDaliRetrieveClusteredCharactersOfCharacterIndex
+//
+//////////////////////////////////////////////////////////
+
+int UtcDaliRetrieveClusteredCharactersOfCharacterIndex(void)
+{
+  tet_infoline(" UtcDaliRetrieveClusteredCharactersOfCharacterIndex");
+
+  CharacterIndex characterIndex01[] = {0u, 1u, 2u, 10u};
+
+  CharacterRun clusteredCharacters01[] = {
+    {0u, 1u},
+    {1u, 1u},
+    {2u, 1u},
+    {10u, 1u}};
+
+  CharacterIndex characterIndex02[] = {0u, 4u, 6u};
+
+  CharacterRun clusteredCharacters02[] = {
+    {0u, 7u},
+    {0u, 7u},
+    {0u, 7u}};
+
+  CharacterIndex characterIndex03[] = {3u, 9u, 14u};
+
+  CharacterRun clusteredCharacters03[] = {
+    {2u, 7u},
+    {9u, 1u},
+    {11u, 4u}};
+
+  CharacterIndex characterIndex04[] = {0u, 1u, 2u, 10u};
+
+  CharacterRun clusteredCharacters04[] = {
+    {0u, 1u},
+    {1u, 1u},
+    {2u, 1u},
+    {10u, 1u}};
+
+  struct RetrieveClusteredCharactersOfCharacterIndexData data[] =
+    {
+      {"Easy latin script",
+       "Hello world",
+       true,
+       4u,
+       characterIndex01,
+       clusteredCharacters01},
+
+      {"FamilyManWomanGirlBoy Single Complex Emoji script",
+       "&#x1F468;&#x200D;&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;",
+       true,
+       3u,
+       characterIndex02,
+       clusteredCharacters02},
+
+      {"Long text many Emojis with letters",
+       "AB&#x1F468;&#x200D;&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;AB&#x1F469;&#x1F3FB;&#x200D;&#x1F52C;B&#x1F468;&#x200D;&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;AA&#x262a;&#xfe0e;B&#x262a;&#xfe0f;AB",
+       true,
+       3u,
+       characterIndex03,
+       clusteredCharacters03},
+
+      {"Arabic script",
+       "اهلا و سهلا",
+       true,
+       4u,
+       characterIndex04,
+       clusteredCharacters04},
+    };
+  const unsigned int numberOfTests = 4u;
+
+  for(unsigned int index = 0; index < numberOfTests; ++index)
+  {
+    ToolkitTestApplication application;
+    if(!GetRetrieveClusteredCharactersOfCharacterIndexTest(data[index]))
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
index 11c6343..cd1abcb 100755 (executable)
@@ -60,14 +60,15 @@ struct GetClosestLineData
 
 struct GetClosestCursorIndexData
 {
-  std::string             description;    ///< Description of the test.
-  std::string             text;           ///< Input text.
-  unsigned int            numberOfTests;  ///< The number of tests.
-  float*                  visualX;        ///< The visual 'x' position for each test.
-  float*                  visualY;        ///< The visual 'y' position for each test.
-  CharacterHitTest::Mode* mode;           ///< The type of hit test.
-  CharacterIndex*         logicalIndex;   ///< The expected logical cursor index for each test.
-  bool*                   isCharacterHit; ///< The expected character hit value for each test.
+  std::string             description;            ///< Description of the test.
+  std::string             text;                   ///< Input text.
+  unsigned int            numberOfTests;          ///< The number of tests.
+  float*                  visualX;                ///< The visual 'x' position for each test.
+  float*                  visualY;                ///< The visual 'y' position for each test.
+  CharacterHitTest::Mode* mode;                   ///< The type of hit test.
+  bool                    markupProcessorEnabled; //< Enable markup processor to use markup text.
+  CharacterIndex*         logicalIndex;           ///< The expected logical cursor index for each test.
+  bool*                   isCharacterHit;         ///< The expected character hit value for each test.
 };
 
 struct GetCursorPositionData
@@ -173,7 +174,7 @@ bool GetClosestCursorIndexTest(const GetClosestCursorIndexData& data)
                   layoutSize,
                   textModel,
                   metrics,
-                  false,
+                  data.markupProcessorEnabled,
                   LineWrap::WORD,
                   false,
                   Toolkit::DevelText::EllipsisPosition::END,
@@ -579,6 +580,12 @@ int UtcDaliGetClosestCursorIndex(void)
   CharacterIndex         logicalIndex08[]   = {1u};
   bool                   isCharacterHit08[] = {true};
 
+  float                  visualX09[]        = {9.f};
+  float                  visualY09[]        = {12.f};
+  CharacterHitTest::Mode mode09[]           = {CharacterHitTest::TAP};
+  CharacterIndex         logicalIndex09[]   = {1u};
+  bool                   isCharacterHit09[] = {true};
+
   struct GetClosestCursorIndexData data[] =
     {
       {"Void text.",
@@ -587,24 +594,30 @@ int UtcDaliGetClosestCursorIndex(void)
        visualX01,
        visualY01,
        mode01,
+       false,
        logicalIndex01,
        isCharacterHit01},
+
       {"Single line text.",
        "Hello world שלום עולם",
        7u,
        visualX02,
        visualY02,
        mode02,
+       false,
        logicalIndex02,
        isCharacterHit02},
+
       {"Single line with ligatures",
        "different الأربعاء",
        4u,
        visualX03,
        visualY03,
        mode03,
+       false,
        logicalIndex03,
        isCharacterHit03},
+
       {"Multiline. Single line paragraphs",
        "Hello world\n"
        "שלום עולם\n"
@@ -613,8 +626,10 @@ int UtcDaliGetClosestCursorIndex(void)
        visualX04,
        visualY04,
        mode04,
+       false,
        logicalIndex04,
        isCharacterHit04},
+
       {"Multiline. Single bidirectional paragraph, starts LTR, wrapped lines",
        "abcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuדאוvwxה"
        "סתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuד"
@@ -626,8 +641,10 @@ int UtcDaliGetClosestCursorIndex(void)
        visualX05,
        visualY05,
        mode05,
+       false,
        logicalIndex05,
        isCharacterHit05},
+
       {"Multiline. Single bidirectional paragraph, starts RTL, wrapped lines",
        "שנבabcגקכdefעיןghiחלךjklצמםmnoפרףpqrדאוstuהסתv"
        "wxטזץyzשנבabcגקכdefעיןghiחלךjklצמםmnoפרףpqrדאוs"
@@ -639,25 +656,42 @@ int UtcDaliGetClosestCursorIndex(void)
        visualX06,
        visualY06,
        mode06,
+       false,
        logicalIndex06,
        isCharacterHit06},
+
       {"Testing complex characters. Arabic ligatures",
        "الأَبْجَدِيَّة العَرَبِيَّة",
        1u,
        visualX07,
        visualY07,
        mode07,
+       false,
        logicalIndex07,
        isCharacterHit07},
+
       {"Testing complex characters. Latin ligatures",
        "fi ligature",
        1u,
        visualX08,
        visualY08,
        mode08,
+       false,
        logicalIndex08,
-       isCharacterHit08}};
-  const unsigned int numberOfTests = 8u;
+       isCharacterHit08},
+
+      {"Testing complex characters. Emoji",
+       "A&#x1F468;&#x200D;&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;B",
+       1u,
+       visualX09,
+       visualY09,
+       mode09,
+       true,
+       logicalIndex09,
+       isCharacterHit09}
+
+    };
+  const unsigned int numberOfTests = 9u;
 
   for(unsigned int index = 0; index < numberOfTests; ++index)
   {
index 7817c02..36117f7 100644 (file)
@@ -178,15 +178,16 @@ bool XHTMLEntityToUTF8Test(const XHTMLEntityToUTF8Data& data)
 {
   std::cout << "  testing " << data.description << std::endl;
 
-  Vector<ColorRun>                  colorRuns;
-  Vector<FontDescriptionRun>        fontRuns;
-  Vector<EmbeddedItem>              items;
-  Vector<Anchor>                    anchors;
-  Vector<UnderlinedCharacterRun>    underlinedCharacterRuns;
-  Vector<ColorRun>                  backgroundColorRuns;
-  Vector<StrikethroughCharacterRun> strikethroughCharacterRuns;
-  Vector<BoundedParagraphRun>       boundedParagraphRuns;
-  MarkupProcessData                 markupProcessData(colorRuns, fontRuns, items, anchors, underlinedCharacterRuns, backgroundColorRuns, strikethroughCharacterRuns, boundedParagraphRuns);
+  Vector<ColorRun>                     colorRuns;
+  Vector<FontDescriptionRun>           fontRuns;
+  Vector<EmbeddedItem>                 items;
+  Vector<Anchor>                       anchors;
+  Vector<UnderlinedCharacterRun>       underlinedCharacterRuns;
+  Vector<ColorRun>                     backgroundColorRuns;
+  Vector<StrikethroughCharacterRun>    strikethroughCharacterRuns;
+  Vector<BoundedParagraphRun>          boundedParagraphRuns;
+  Vector<CharacterSpacingCharacterRun> characterSpacingCharacterRuns;
+  MarkupProcessData                    markupProcessData(colorRuns, fontRuns, items, anchors, underlinedCharacterRuns, backgroundColorRuns, strikethroughCharacterRuns, boundedParagraphRuns, characterSpacingCharacterRuns);
   ProcessMarkupString(data.xHTMLEntityString, markupProcessData);
 
   for(Vector<EmbeddedItem>::Iterator it    = items.Begin(),
index d19326f..f768255 100644 (file)
@@ -1327,3 +1327,118 @@ int UtcDaliTextEditorMarkupParagraphTagAlignAttribute(void)
 
   END_TEST;
 }
+
+int UtcDaliTextEditorMarkupCharacterSpacingTag(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextEditorMarkupCharacterSpacingTag ");
+
+  const Length EXPECTED_NUMBER_OF_GLYPHS = 21u;
+
+  const float expandedCharSpacing  = 10.0f;
+  const float condensedCharSpacing = -5.0f;
+
+  TextEditor textEditor = TextEditor::New();
+
+  textEditor.SetProperty(TextEditor::Property::TEXT, "ABC EF\n<char-spacing value='-5.0f'>ABC EF\n</char-spacing><char-spacing value='10.0f'>ABC EF\n</char-spacing>");
+  textEditor.SetProperty(TextEditor ::Property::ENABLE_MARKUP, true);
+
+  application.GetScene().Add(textEditor);
+
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextEditor& textEditorImpl = GetImpl(textEditor);
+  Text::ViewInterface&           view           = textEditorImpl.GetTextController()->GetView();
+
+  Length numberOfGlyphs = view.GetNumberOfGlyphs();
+
+  DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  Vector<GlyphInfo> glyphs;
+  glyphs.Resize(numberOfGlyphs);
+
+  Vector<Vector2> positions;
+  positions.Resize(numberOfGlyphs);
+
+  float alignmentOffset = 0u;
+  numberOfGlyphs        = view.GetGlyphs(glyphs.Begin(),
+                                  positions.Begin(),
+                                  alignmentOffset,
+                                  0u,
+                                  numberOfGlyphs);
+
+  const Length numberOfGlyphsOneLine = 7u;
+  for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++)
+  {
+    float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x;
+
+    float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x;
+    DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+    float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x;
+    DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliTextEditorMarkupSpanCharacterSpacing(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextEditorMarkupSpanCharacterSpacing ");
+
+  const Length EXPECTED_NUMBER_OF_GLYPHS = 21u;
+
+  const float expandedCharSpacing  = 10.0f;
+  const float condensedCharSpacing = -5.0f;
+
+  std::string testText =
+    "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='blue' >ABC EF\n</span>"
+    "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' char-space-value='-5.0f'>ABC EF\n</span>"
+    "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='green' char-space-value='10.0f'>ABC EF\n</span>";
+
+  TextEditor textEditor = TextEditor::New();
+
+  textEditor.SetProperty(TextEditor::Property::TEXT, testText);
+  textEditor.SetProperty(TextEditor ::Property::ENABLE_MARKUP, true);
+
+  application.GetScene().Add(textEditor);
+
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextEditor& textEditorImpl = GetImpl(textEditor);
+  Text::ViewInterface&           view           = textEditorImpl.GetTextController()->GetView();
+
+  Length numberOfGlyphs = view.GetNumberOfGlyphs();
+
+  DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  Vector<GlyphInfo> glyphs;
+  glyphs.Resize(numberOfGlyphs);
+
+  Vector<Vector2> positions;
+  positions.Resize(numberOfGlyphs);
+
+  float alignmentOffset = 0u;
+  numberOfGlyphs        = view.GetGlyphs(glyphs.Begin(),
+                                  positions.Begin(),
+                                  alignmentOffset,
+                                  0u,
+                                  numberOfGlyphs);
+
+  const Length numberOfGlyphsOneLine = 7u;
+  for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++)
+  {
+    float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x;
+
+    float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x;
+    DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+    float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x;
+    DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  }
+
+  END_TEST;
+}
\ No newline at end of file
index 02aa540..da3ffc3 100644 (file)
@@ -1235,4 +1235,119 @@ int UtcDaliTextFieldMarkupStrikethroughNoEndTag(void)
   DALI_TEST_EQUALS(numberOfStrikethroughRuns, expectedNumberOfStrikethroughGlyphs, TEST_LOCATION);
 
   END_TEST;
+}
+
+int UtcDaliTextFieldMarkupCharacterSpacingTag(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextFieldMarkupCharacterSpacingTag ");
+
+  const Length EXPECTED_NUMBER_OF_GLYPHS = 21u;
+
+  const float expandedCharSpacing  = 10.0f;
+  const float condensedCharSpacing = -5.0f;
+
+  TextField textField = TextField::New();
+
+  textField.SetProperty(TextField::Property::TEXT, "ABC EF\n<char-spacing value='-5.0f'>ABC EF\n</char-spacing><char-spacing value='10.0f'>ABC EF\n</char-spacing>");
+  textField.SetProperty(TextField ::Property::ENABLE_MARKUP, true);
+
+  application.GetScene().Add(textField);
+
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextField& textFieldImpl = GetImpl(textField);
+  Text::ViewInterface&          view          = textFieldImpl.GetTextController()->GetView();
+
+  Length numberOfGlyphs = view.GetNumberOfGlyphs();
+
+  DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  Vector<GlyphInfo> glyphs;
+  glyphs.Resize(numberOfGlyphs);
+
+  Vector<Vector2> positions;
+  positions.Resize(numberOfGlyphs);
+
+  float alignmentOffset = 0u;
+  numberOfGlyphs        = view.GetGlyphs(glyphs.Begin(),
+                                  positions.Begin(),
+                                  alignmentOffset,
+                                  0u,
+                                  numberOfGlyphs);
+
+  const Length numberOfGlyphsOneLine = 7u;
+  for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++)
+  {
+    float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x;
+
+    float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x;
+    DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+    float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x;
+    DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliTextFieldMarkupSpanCharacterSpacing(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextFieldMarkupSpanCharacterSpacing ");
+
+  const Length EXPECTED_NUMBER_OF_GLYPHS = 21u;
+
+  const float expandedCharSpacing  = 10.0f;
+  const float condensedCharSpacing = -5.0f;
+
+  std::string testText =
+    "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='blue' >ABC EF\n</span>"
+    "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' char-space-value='-5.0f'>ABC EF\n</span>"
+    "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='green' char-space-value='10.0f'>ABC EF\n</span>";
+
+  TextField textField = TextField::New();
+
+  textField.SetProperty(TextField::Property::TEXT, testText);
+  textField.SetProperty(TextField ::Property::ENABLE_MARKUP, true);
+
+  application.GetScene().Add(textField);
+
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextField& textFieldImpl = GetImpl(textField);
+  Text::ViewInterface&          view          = textFieldImpl.GetTextController()->GetView();
+
+  Length numberOfGlyphs = view.GetNumberOfGlyphs();
+
+  DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  Vector<GlyphInfo> glyphs;
+  glyphs.Resize(numberOfGlyphs);
+
+  Vector<Vector2> positions;
+  positions.Resize(numberOfGlyphs);
+
+  float alignmentOffset = 0u;
+  numberOfGlyphs        = view.GetGlyphs(glyphs.Begin(),
+                                  positions.Begin(),
+                                  alignmentOffset,
+                                  0u,
+                                  numberOfGlyphs);
+
+  const Length numberOfGlyphsOneLine = 7u;
+  for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++)
+  {
+    float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x;
+
+    float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x;
+    DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+    float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x;
+    DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  }
+
+  END_TEST;
 }
\ No newline at end of file
index 1ac00b5..d9a3c04 100644 (file)
@@ -1221,3 +1221,120 @@ int UtcDaliTextLabelMarkupParagraphTagAlignAttribute(void)
 
   END_TEST;
 }
+
+int UtcDaliTextLabelMarkupCharacterSpacingTag(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLabelMarkupCharacterSpacingTag ");
+
+  const Length EXPECTED_NUMBER_OF_GLYPHS = 21u;
+
+  const float expandedCharSpacing  = 10.0f;
+  const float condensedCharSpacing = -5.0f;
+
+  TextLabel textLabel = TextLabel::New();
+
+  textLabel.SetProperty(TextLabel::Property::TEXT, "ABC EF\n<char-spacing value='-5.0f'>ABC EF\n</char-spacing><char-spacing value='10.0f'>ABC EF\n</char-spacing>");
+  textLabel.SetProperty(TextLabel ::Property::ENABLE_MARKUP, true);
+  textLabel.SetProperty(TextLabel::Property::MULTI_LINE, true);
+
+  application.GetScene().Add(textLabel);
+
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextLabel& textLabelImpl = GetImpl(textLabel);
+  Text::ViewInterface&          view          = textLabelImpl.GetTextController()->GetView();
+
+  Length numberOfGlyphs = view.GetNumberOfGlyphs();
+
+  DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  Vector<GlyphInfo> glyphs;
+  glyphs.Resize(numberOfGlyphs);
+
+  Vector<Vector2> positions;
+  positions.Resize(numberOfGlyphs);
+
+  float alignmentOffset = 0u;
+  numberOfGlyphs        = view.GetGlyphs(glyphs.Begin(),
+                                  positions.Begin(),
+                                  alignmentOffset,
+                                  0u,
+                                  numberOfGlyphs);
+
+  const Length numberOfGlyphsOneLine = 7u;
+  for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++)
+  {
+    float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x;
+
+    float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x;
+    DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+    float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x;
+    DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliTextLabelMarkupSpanCharacterSpacing(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLabelMarkupSpanCharacterSpacing ");
+
+  const Length EXPECTED_NUMBER_OF_GLYPHS = 21u;
+
+  const float expandedCharSpacing  = 10.0f;
+  const float condensedCharSpacing = -5.0f;
+
+  std::string testText =
+    "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='blue' >ABC EF\n</span>"
+    "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' char-space-value='-5.0f'>ABC EF\n</span>"
+    "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='green' char-space-value='10.0f'>ABC EF\n</span>";
+
+  TextLabel textLabel = TextLabel::New();
+
+  textLabel.SetProperty(TextLabel::Property::TEXT, testText);
+  textLabel.SetProperty(TextLabel ::Property::ENABLE_MARKUP, true);
+  textLabel.SetProperty(TextLabel::Property::MULTI_LINE, true);
+
+  application.GetScene().Add(textLabel);
+
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextLabel& textLabelImpl = GetImpl(textLabel);
+  Text::ViewInterface&          view          = textLabelImpl.GetTextController()->GetView();
+
+  Length numberOfGlyphs = view.GetNumberOfGlyphs();
+
+  DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  Vector<GlyphInfo> glyphs;
+  glyphs.Resize(numberOfGlyphs);
+
+  Vector<Vector2> positions;
+  positions.Resize(numberOfGlyphs);
+
+  float alignmentOffset = 0u;
+  numberOfGlyphs        = view.GetGlyphs(glyphs.Begin(),
+                                  positions.Begin(),
+                                  alignmentOffset,
+                                  0u,
+                                  numberOfGlyphs);
+
+  const Length numberOfGlyphsOneLine = 7u;
+  for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++)
+  {
+    float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x;
+
+    float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x;
+    DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+    float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x;
+    DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  }
+
+  END_TEST;
+}
\ No newline at end of file
index ab2548a..000bfa7 100755 (executable)
@@ -1455,6 +1455,11 @@ public:
     return mScaleFactor;
   }
 
+  Dali::Accessibility::Address GetAccessibilityAddress()
+  {
+    return {":9.99", "root"};
+  }
+
   Dali::PixelData GetScreenshot(Dali::Rect<int32_t> viewArea, float scaleFactor)
   {
     uint32_t bufferSize = viewArea.width * viewArea.height * 4 ;
@@ -2226,6 +2231,11 @@ void WebEngine::ActivateAccessibility(bool activated)
 {
 }
 
+Accessibility::Address WebEngine::GetAccessibilityAddress()
+{
+  return Internal::Adaptor::GetImplementation(*this).GetAccessibilityAddress();
+}
+
 bool WebEngine::HighlightText(const std::string& text, Dali::WebEnginePlugin::FindOption options, uint32_t maxMatchCount)
 {
   return true;
@@ -2471,4 +2481,3 @@ void WebEngine::GetPlainTextAsynchronously(Dali::WebEnginePlugin::PlainTextRecei
 }
 
 } // namespace Dali;
-
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 9d9567b..c21f9a3 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;
 }
 
@@ -5924,4 +5947,83 @@ int UtcDaliToolkitTexteditorParagraphTag(void)
   application.Render();
 
   END_TEST;
+}
+
+//Handle Emoji clustering for cursor handling
+int utcDaliTextEditorClusteredEmojiDeletionBackSpaceKey(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" utcDaliTextEditorClusteredEmojiDeletionBackSpaceKey ");
+  TextEditor textEditor = TextEditor::New();
+  DALI_TEST_CHECK(textEditor);
+
+  application.GetScene().Add(textEditor);
+
+  // Avoid a crash when core load gl resources.
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE);
+
+  textEditor.SetProperty(TextEditor::Property::TEXT, "ABC&#x1F468;&#x200D;&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;XY");
+  textEditor.SetProperty(Dali::Toolkit::TextEditor::Property::ENABLE_MARKUP, true);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Set currsor
+  textEditor.SetProperty(DevelTextEditor::Property::PRIMARY_CURSOR_POSITION, 10);
+  application.SendNotification();
+  application.Render();
+
+  // Set focus and remove Emoji
+  textEditor.SetKeyInputFocus();
+  application.ProcessEvent(GenerateKey("", "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+  //Check the changed text and cursor position
+  DALI_TEST_EQUALS(textEditor.GetProperty(TextEditor::Property::TEXT).Get<std::string>(), "ABCXY", TEST_LOCATION);
+  DALI_TEST_EQUALS(textEditor.GetProperty(DevelTextEditor::Property::PRIMARY_CURSOR_POSITION).Get<int>(), 3, TEST_LOCATION);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  END_TEST;
+}
+
+int utcDaliTextEditorClusteredEmojiDeletionDeleteKey(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" utcDaliTextEditorClusteredEmojiDeletionDeleteKey ");
+  TextEditor textEditor = TextEditor::New();
+  DALI_TEST_CHECK(textEditor);
+
+  application.GetScene().Add(textEditor);
+
+  // Avoid a crash when core load gl resources.
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE);
+
+  textEditor.SetProperty(TextEditor::Property::TEXT, "ABC&#x1F468;&#x200D;&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;XY");
+  textEditor.SetProperty(Dali::Toolkit::TextEditor::Property::ENABLE_MARKUP, true);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Set currsor
+  textEditor.SetProperty(DevelTextEditor::Property::PRIMARY_CURSOR_POSITION, 3);
+  application.SendNotification();
+  application.Render();
+
+  // Set focus and remove Emoji
+  textEditor.SetKeyInputFocus();
+  application.ProcessEvent(GenerateKey("", "", "", Dali::DevelKey::DALI_KEY_DELETE, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+  //Check the changed text and cursor position
+  DALI_TEST_EQUALS(textEditor.GetProperty(TextEditor::Property::TEXT).Get<std::string>(), "ABCXY", TEST_LOCATION);
+  DALI_TEST_EQUALS(textEditor.GetProperty(DevelTextEditor::Property::PRIMARY_CURSOR_POSITION).Get<int>(), 3, TEST_LOCATION);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  END_TEST;
 }
\ No newline at end of file
index 3f5ff1b..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;
 }
 
@@ -5319,4 +5341,83 @@ int UtcDaliToolkitTextfieldParagraphTag(void)
   application.Render();
 
   END_TEST;
+}
+
+//Handle Emoji clustering for cursor handling
+int utcDaliTextFieldClusteredEmojiDeletionBackSpaceKey(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" utcDaliTextFieldClusteredEmojiDeletionBackSpaceKey ");
+  TextField textField = TextField::New();
+  DALI_TEST_CHECK(textField);
+
+  application.GetScene().Add(textField);
+
+  // Avoid a crash when core load gl resources.
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE);
+
+  textField.SetProperty(TextField::Property::TEXT, "ABC&#x1F468;&#x200D;&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;XY");
+  textField.SetProperty(Dali::Toolkit::TextField::Property::ENABLE_MARKUP, true);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Set currsor
+  textField.SetProperty(DevelTextField::Property::PRIMARY_CURSOR_POSITION, 10);
+  application.SendNotification();
+  application.Render();
+
+  // Set focus and remove Emoji
+  textField.SetKeyInputFocus();
+  application.ProcessEvent(GenerateKey("", "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+  //Check the changed text and cursor position
+  DALI_TEST_EQUALS(textField.GetProperty(TextField::Property::TEXT).Get<std::string>(), "ABCXY", TEST_LOCATION);
+  DALI_TEST_EQUALS(textField.GetProperty(DevelTextField::Property::PRIMARY_CURSOR_POSITION).Get<int>(), 3, TEST_LOCATION);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  END_TEST;
+}
+
+int utcDaliTextFieldClusteredEmojiDeletionDeleteKey(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" utcDaliTextFieldClusteredEmojiDeletionDeleteKey ");
+  TextField textField = TextField::New();
+  DALI_TEST_CHECK(textField);
+
+  application.GetScene().Add(textField);
+
+  // Avoid a crash when core load gl resources.
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE);
+
+  textField.SetProperty(TextField::Property::TEXT, "ABC&#x1F468;&#x200D;&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;XY");
+  textField.SetProperty(Dali::Toolkit::TextField::Property::ENABLE_MARKUP, true);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Set currsor
+  textField.SetProperty(DevelTextField::Property::PRIMARY_CURSOR_POSITION, 3);
+  application.SendNotification();
+  application.Render();
+
+  // Set focus and remove Emoji
+  textField.SetKeyInputFocus();
+  application.ProcessEvent(GenerateKey("", "", "", Dali::DevelKey::DALI_KEY_DELETE, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+  //Check the changed text and cursor position
+  DALI_TEST_EQUALS(textField.GetProperty(TextField::Property::TEXT).Get<std::string>(), "ABCXY", TEST_LOCATION);
+  DALI_TEST_EQUALS(textField.GetProperty(DevelTextField::Property::PRIMARY_CURSOR_POSITION).Get<int>(), 3, TEST_LOCATION);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  END_TEST;
 }
\ No newline at end of file
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 7b5e36e..c9ab7b5 100644 (file)
@@ -36,6 +36,7 @@
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
 #include <dali-toolkit/internal/text/markup-processor.h>
 #include <dali-toolkit/internal/text/multi-language-support.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
 #include <dali-toolkit/internal/text/segmentation.h>
 #include <dali-toolkit/internal/text/shaper.h>
 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
@@ -178,7 +179,8 @@ void ShapeTextPreprocess(const RendererParameters& textParameters, TextAbstracti
                                       textModel->mLogicalModel->mUnderlinedCharacterRuns,
                                       textModel->mLogicalModel->mBackgroundColorRuns,
                                       textModel->mLogicalModel->mStrikethroughCharacterRuns,
-                                      textModel->mLogicalModel->mBoundedParagraphRuns);
+                                      textModel->mLogicalModel->mBoundedParagraphRuns,
+                                      textModel->mLogicalModel->mCharacterSpacingCharacterRuns);
 
   if(textParameters.markupEnabled)
   {
@@ -819,10 +821,14 @@ void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRen
   Vector<LineRun>&        lines                     = textModel->mVisualModel->mLines; // The laid out lines.
   Vector<bool>&           isEmoji                   = internalDataModel.isEmoji;
   const Size              textLayoutArea            = internalDataModel.textLayoutArea;
-  const float             characterSpacing          = textModel->mVisualModel->GetCharacterSpacing();
+  const float             modelCharacterSpacing     = textModel->mVisualModel->GetCharacterSpacing();
   float                   calculatedAdvance         = 0.f;
   Vector<CharacterIndex>& glyphToCharacterMap       = textModel->mVisualModel->mGlyphsToCharacters;
   const CharacterIndex*   glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
+
+  // Get the character-spacing runs.
+  const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = textModel->mVisualModel->GetCharacterSpacingGlyphRuns();
+
   ////////////////////////////////////////////////////////////////////////////////
   // Ellipsis the text.
   ////////////////////////////////////////////////////////////////////////////////
@@ -908,7 +914,8 @@ void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRen
                 firstPenSet = true;
               }
 
-              calculatedAdvance = GetCalculatedAdvance(*(textModel->mLogicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyphToRemove.advance);
+              const float characterSpacing = GetGlyphCharacterSpacing(index, characterSpacingGlyphRuns, modelCharacterSpacing);
+              calculatedAdvance            = GetCalculatedAdvance(*(textModel->mLogicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyphToRemove.advance);
               removedGlypsWidth += std::min(calculatedAdvance, (glyphToRemove.xBearing + glyphToRemove.width));
 
               // Calculate the width of the ellipsis glyph and check if it fits.
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 0a8c129..7fc2117 100755 (executable)
@@ -204,6 +204,13 @@ void WebView::OnInitialize()
     mWebSettings        = std::unique_ptr<Dali::Toolkit::WebSettings>(new WebSettings(mWebEngine.GetSettings()));
     mWebBackForwardList = std::unique_ptr<Dali::Toolkit::WebBackForwardList>(new WebBackForwardList(mWebEngine.GetBackForwardList()));
   }
+
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
+}
+
+DevelControl::ControlAccessible* WebView::CreateAccessibleObject()
+{
+  return new WebViewAccessible(Self(), mWebEngine);
 }
 
 Dali::Toolkit::WebSettings* WebView::GetSettings() const
@@ -1236,6 +1243,58 @@ bool WebView::SetVisibility(bool visible)
   return mWebEngine ? mWebEngine.SetVisibility(visible) : false;
 }
 
+WebView::WebViewAccessible::WebViewAccessible(Dali::Actor self, Dali::WebEngine& webEngine)
+: ControlAccessible(self), mRemoteChild{}, mWebEngine{webEngine}
+{
+  Dali::Accessibility::Bridge::EnabledSignal().Connect(this, &WebViewAccessible::OnAccessibilityEnabled);
+  Dali::Accessibility::Bridge::DisabledSignal().Connect(this, &WebViewAccessible::OnAccessibilityDisabled);
+
+  if(Dali::Accessibility::IsUp())
+  {
+    OnAccessibilityEnabled();
+  }
+  else
+  {
+    OnAccessibilityDisabled();
+  }
+}
+
+void WebView::WebViewAccessible::DoGetChildren(std::vector<Dali::Accessibility::Accessible*>& children)
+{
+  if(mRemoteChild.GetAddress())
+  {
+    children.push_back(&mRemoteChild);
+  }
+}
+
+void WebView::WebViewAccessible::OnAccessibilityEnabled()
+{
+  if(!mWebEngine)
+  {
+    return;
+  }
+
+  mWebEngine.ActivateAccessibility(true);
+  SetRemoteChildAddress(mWebEngine.GetAccessibilityAddress());
+}
+
+void WebView::WebViewAccessible::OnAccessibilityDisabled()
+{
+  if(!mWebEngine)
+  {
+    return;
+  }
+
+  SetRemoteChildAddress({});
+  mWebEngine.ActivateAccessibility(false);
+}
+
+void WebView::WebViewAccessible::SetRemoteChildAddress(Dali::Accessibility::Address address)
+{
+  mRemoteChild.SetAddress(std::move(address));
+  OnChildrenChanged();
+}
+
 #undef GET_ENUM_STRING
 #undef GET_ENUM_VALUE
 
index 2d8a523..6a0da6e 100755 (executable)
 
 // EXTERNAL INCLUDES
 #include <dali/devel-api/actors/actor-devel.h>
+#include <dali/devel-api/adaptor-framework/proxy-accessible.h>
 #include <dali/devel-api/adaptor-framework/web-engine.h>
 #include <dali/public-api/images/image-operations.h>
 #include <dali/public-api/object/property-notification.h>
 #include <memory>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-accessible.h>
 #include <dali-toolkit/devel-api/controls/web-view/web-view.h>
 #include <dali-toolkit/devel-api/visual-factory/visual-base.h>
 #include <dali-toolkit/public-api/controls/control-impl.h>
@@ -423,6 +425,11 @@ private: // From Control
   void OnInitialize() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * @copydoc Toolkit::Control::GetNaturalSize
    */
   Vector3 GetNaturalSize() override;
@@ -663,6 +670,29 @@ private:
    */
   void OnScreenshotCaptured(Dali::PixelData pixel);
 
+protected:
+  class WebViewAccessible : public DevelControl::ControlAccessible
+  {
+  public:
+    WebViewAccessible() = delete;
+
+    WebViewAccessible(Dali::Actor self, Dali::WebEngine& webEngine);
+
+  protected:
+    /**
+     * @copydoc Dali::Accessibility::ActorAccessible::DoGetChildren()
+     */
+    void DoGetChildren(std::vector<Dali::Accessibility::Accessible*>& children) override;
+
+  private:
+    void OnAccessibilityEnabled();
+    void OnAccessibilityDisabled();
+    void SetRemoteChildAddress(Dali::Accessibility::Address address);
+
+    Dali::Accessibility::ProxyAccessible mRemoteChild;
+    Dali::WebEngine&                     mWebEngine;
+  };
+
 private:
   Dali::Toolkit::Visual::Base mVisual;
   Dali::Size                  mWebViewSize;
index 7e9c1aa..355667e 100644 (file)
@@ -140,6 +140,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/bidirectional-support.cpp
    ${toolkit_src_dir}/text/bounded-paragraph-helper-functions.cpp
    ${toolkit_src_dir}/text/character-set-conversion.cpp
+   ${toolkit_src_dir}/text/characters-helper-functions.cpp
    ${toolkit_src_dir}/text/color-segmentation.cpp
    ${toolkit_src_dir}/text/cursor-helper-functions.cpp
    ${toolkit_src_dir}/text/glyph-metrics-helper.cpp
@@ -154,6 +155,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/markup-processor-span.cpp
    ${toolkit_src_dir}/text/markup-processor-strikethrough.cpp
    ${toolkit_src_dir}/text/markup-processor-underline.cpp
+   ${toolkit_src_dir}/text/markup-processor-character-spacing.cpp
    ${toolkit_src_dir}/text/markup-processor-helper-functions.cpp
    ${toolkit_src_dir}/text/markup-processor-attribute-helper-functions.cpp
    ${toolkit_src_dir}/text/multi-language-support.cpp
@@ -203,7 +205,8 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/rendering/text-typesetter.cpp
    ${toolkit_src_dir}/text/rendering/view-model.cpp
    ${toolkit_src_dir}/text/rendering/styles/underline-helper-functions.cpp
-   ${toolkit_src_dir}/text/rendering/styles/strikethrough-helper-functions
+   ${toolkit_src_dir}/text/rendering/styles/strikethrough-helper-functions.cpp
+   ${toolkit_src_dir}/text/rendering/styles/character-spacing-helper-functions.cpp
    ${toolkit_src_dir}/transition/fade-transition-impl.cpp
    ${toolkit_src_dir}/transition/slide-transition-impl.cpp
    ${toolkit_src_dir}/transition/scale-transition-impl.cpp
index 977e2e0..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,18 +244,13 @@ 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))
     {
       actor.Add(GetFocusIndicatorActor());
     }
 
-    // Send notification for the change of focus actor
-    if(!mFocusChangedSignal.Empty())
-    {
-      mFocusChangedSignal.Emit(currentFocusedActor, actor);
-    }
 
     Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast(currentFocusedActor);
     if(currentlyFocusedControl)
@@ -265,8 +260,6 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor)
       currentlyFocusedControl.ClearKeyInputFocus();
     }
 
-    DALI_LOG_INFO(gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__);
-
     // Save the current focused actor
     mCurrentFocusActor = actor;
 
@@ -303,6 +296,11 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor)
       mFocusHistory.erase(beginPos);
     }
 
+    // Send notification for the change of focus actor
+    if(!mFocusChangedSignal.Empty())
+    {
+      mFocusChangedSignal.Emit(currentFocusedActor, actor);
+    }
     DALI_LOG_INFO(gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__);
     success = true;
   }
@@ -554,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))
@@ -580,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);
@@ -599,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))
@@ -681,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())
     {
@@ -702,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;
 }
 
@@ -1005,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&);
diff --git a/dali-toolkit/internal/text/character-spacing-character-run.h b/dali-toolkit/internal/text/character-spacing-character-run.h
new file mode 100644 (file)
index 0000000..5c4238e
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef DALI_TOOLKIT_TEXT_CHARACTER_SPACING_CHARACTER_RUN_H
+#define DALI_TOOLKIT_TEXT_CHARACTER_SPACING_CHARACTER_RUN_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/math/vector4.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-run.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+ * @brief Run of character-spacing characters with same properties.
+ */
+struct CharacterSpacingCharacterRun
+{
+  /**
+   * Default constructor to set the default values of bitfields
+   */
+  CharacterSpacingCharacterRun()
+  : characterRun{},
+    value{0.f} //The default value is 0.f which does nothing.
+  {
+  }
+
+  CharacterRun characterRun; ///< The initial character index and the number of characters of the run.
+  float        value;        /// 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).
+
+  //TODO: Add unit property to choose between Pixel or Scale (%)
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_CHARACTER_SPACING_CHARACTER_RUN_H
diff --git a/dali-toolkit/internal/text/character-spacing-glyph-run.h b/dali-toolkit/internal/text/character-spacing-glyph-run.h
new file mode 100644 (file)
index 0000000..7375533
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef DALI_TOOLKIT_TEXT_CHARACTER_SPACING_GLYPH_RUN_H
+#define DALI_TOOLKIT_TEXT_CHARACTER_SPACING_GLYPH_RUN_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/math/vector4.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/glyph-run.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+ * @brief Run of character-spacing glyphs with same properties.
+ */
+struct CharacterSpacingGlyphRun
+{
+  /**
+   * Default constructor to set the default values of bitfields
+   */
+  CharacterSpacingGlyphRun()
+  : glyphRun{},
+    value{0.f} //The default value is 0.f which does nothing.
+  {
+  }
+
+  GlyphRun glyphRun; ///< The initial glyph index and the number of glyphs in the run.
+  float    value;    ///< The spaces between characters in Pixels.
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_CHARACTER_SPACING_GLYPH_RUN_H
diff --git a/dali-toolkit/internal/text/characters-helper-functions.cpp b/dali-toolkit/internal/text/characters-helper-functions.cpp
new file mode 100644 (file)
index 0000000..d89f1fb
--- /dev/null
@@ -0,0 +1,60 @@
+// FILE HEADER
+#include <dali-toolkit/internal/text/characters-helper-functions.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/emoji-helper.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+CharacterRun RetrieveClusteredCharactersOfCharacterIndex(const VisualModelPtr&  visualModel,
+                                                         const LogicalModelPtr& logicalModel,
+                                                         const CharacterIndex&  characterIndex)
+{
+  // Initialization
+  CharacterRun clusteredCharacters;
+  clusteredCharacters.characterIndex     = characterIndex;
+  clusteredCharacters.numberOfCharacters = 1u;
+
+  const GlyphIndex* const     charactersToGlyphBuffer  = visualModel->mCharactersToGlyph.Begin();
+  const Length* const         charactersPerGlyphBuffer = visualModel->mCharactersPerGlyph.Begin();
+  const CharacterIndex* const glyphsToCharacters       = visualModel->mGlyphsToCharacters.Begin();
+
+  GlyphIndex glyphIndex               = *(charactersToGlyphBuffer + characterIndex);
+  Length     actualNumberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex);
+
+  if(actualNumberOfCharacters > 1u)
+  {
+    const Script script = logicalModel->GetScript(characterIndex);
+    // Prevents to break the Latin ligatures like fi, ff, or Arabic ﻻ, ...
+    // Keep actual index of character as is. Because these characters cannot be clustered.
+
+    if(!HasLigatureMustBreak(script))
+    {
+      clusteredCharacters.numberOfCharacters = actualNumberOfCharacters;
+      clusteredCharacters.characterIndex     = *(glyphsToCharacters + glyphIndex); // firstCharacterIndex
+    }
+  }
+  else
+  {
+    while(0u == actualNumberOfCharacters)
+    {
+      ++glyphIndex;
+      actualNumberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex);
+    }
+
+    clusteredCharacters.characterIndex     = *(glyphsToCharacters + glyphIndex); // firstCharacterIndex
+    clusteredCharacters.numberOfCharacters = actualNumberOfCharacters;
+  }
+
+  return clusteredCharacters;
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/characters-helper-functions.h b/dali-toolkit/internal/text/characters-helper-functions.h
new file mode 100644 (file)
index 0000000..00b1b4e
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef DALI_TOOLKIT_TEXT_CHARACTERS_HELPER_FUNCTIONS_H
+#define DALI_TOOLKIT_TEXT_CHARACTERS_HELPER_FUNCTIONS_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-run.h>
+#include <dali-toolkit/internal/text/text-definitions.h>
+#include <dali-toolkit/internal/text/text-model.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+ * @brief Retrieve the clustered consecutive characters that contains current character index.
+ * Found the first index of clustered characters and number of characters.
+ *
+ * @param[in] visualModel The visual model.
+ * @param[in] logicalModel The logical model.
+ * @param[in] characterIndex The character index.
+ *
+ * @return CharacterRun for the clustered characters contains character Index
+ */
+CharacterRun RetrieveClusteredCharactersOfCharacterIndex(const VisualModelPtr&  visualModel,
+                                                         const LogicalModelPtr& logicalModel,
+                                                         const CharacterIndex&  characterIndex);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_CHARACTERS_HELPER_FUNCTIONS_H
\ No newline at end of file
index 3bfc059..5dfebde 100644 (file)
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/characters-helper-functions.h>
+#include <dali-toolkit/internal/text/emoji-helper.h>
 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
 
 namespace
 {
@@ -214,7 +217,10 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr         visualModel,
   {
     return logicalIndex;
   }
-  const float characterSpacing = visualModel->GetCharacterSpacing();
+
+  // Get the character-spacing runs.
+  const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns();
+  const float                             modelCharacterSpacing     = visualModel->GetCharacterSpacing();
 
   // Whether there is a hit on a line.
   bool matchedLine = false;
@@ -289,7 +295,8 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr         visualModel,
 
       // Get the metrics for the group of glyphs.
       GlyphMetrics glyphMetrics;
-      calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + firstLogicalGlyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + firstLogicalGlyphIndex)).advance);
+      const float  characterSpacing = GetGlyphCharacterSpacing(firstLogicalGlyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+      calculatedAdvance             = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + firstLogicalGlyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + firstLogicalGlyphIndex)).advance);
       GetGlyphsMetrics(firstLogicalGlyphIndex,
                        numberOfGlyphs,
                        glyphMetrics,
@@ -458,6 +465,19 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr         visualModel,
 
   logicalIndex = (bidiLineFetched ? logicalModel->GetLogicalCursorIndex(visualIndex) : visualIndex);
 
+  // Handle Emoji clustering for cursor handling:
+  // Fixing this case:
+  // - When there is Emoji contains multi unicodes and it is layoutted at the end of line (LineWrap case , is not new line case)
+  // - Try to click at the center or at the end of Emoji then the cursor appears inside Emoji
+  // - Example:"FamilyManWomanGirlBoy &#x1F468;&#x200D;&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;"
+  const Script script = logicalModel->GetScript(logicalIndex);
+  if(IsOneOfEmojiScripts(script))
+  {
+    //TODO: Use this clustering for Emoji cases only. This needs more testing to generalize to all scripts.
+    CharacterRun emojiClusteredCharacters = RetrieveClusteredCharactersOfCharacterIndex(visualModel, logicalModel, logicalIndex);
+    logicalIndex                          = emojiClusteredCharacters.characterIndex;
+  }
+
   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "closest visualIndex %d logicalIndex %d\n", visualIndex, logicalIndex);
 
   DALI_ASSERT_DEBUG((logicalIndex <= logicalModel->mText.Count() && logicalIndex >= 0) && "GetClosestCursorIndex - Out of bounds index");
@@ -606,7 +626,9 @@ void GetCursorPosition(GetCursorPositionParameters& parameters,
     const Length* const         charactersPerGlyphBuffer = parameters.visualModel->mCharactersPerGlyph.Begin();
     const CharacterIndex* const glyphsToCharactersBuffer = parameters.visualModel->mGlyphsToCharacters.Begin();
     const Vector2* const        glyphPositionsBuffer     = parameters.visualModel->mGlyphPositions.Begin();
-    const float                 characterSpacing         = parameters.visualModel->GetCharacterSpacing();
+    const float                 modelCharacterSpacing    = parameters.visualModel->GetCharacterSpacing();
+
+    const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = parameters.visualModel->GetCharacterSpacingGlyphRuns();
 
     // Get the metrics for the group of glyphs.
     GetGlyphMetricsFromCharacterIndex(index, parameters.visualModel, parameters.logicalModel, metrics, glyphMetrics, glyphIndex, numberOfGlyphs);
@@ -723,6 +745,7 @@ void GetCursorPosition(GetCursorPositionParameters& parameters,
       const bool addGlyphAdvance = ((!isFirstPositionOfLine && !isCurrentRightToLeft) ||
                                     (isFirstPositionOfLine && !isRightToLeftParagraph));
 
+      const float characterSpacing   = GetGlyphCharacterSpacing(secondaryGlyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
       cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + secondaryPosition.x + (addGlyphAdvance ? (glyphMetrics.advance + characterSpacing) : 0.f);
       cursorInfo.secondaryPosition.y = cursorInfo.lineOffset + cursorInfo.lineHeight - cursorInfo.secondaryCursorHeight;
 
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 01c62c7..c46fefd 100644 (file)
@@ -19,6 +19,9 @@
 // FILE HEADER
 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
+
 namespace Dali
 {
 namespace Toolkit
@@ -114,7 +117,10 @@ void GetGlyphMetricsFromCharacterIndex(CharacterIndex         index,
   const GlyphInfo* const  glyphInfoBuffer           = visualModel->mGlyphs.Begin();
   Vector<CharacterIndex>& glyphToCharacterMap       = visualModel->mGlyphsToCharacters;
   const CharacterIndex*   glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
-  const float             characterSpacing          = visualModel->GetCharacterSpacing();
+  const float             modelCharacterSpacing     = visualModel->GetCharacterSpacing();
+
+  // Get the character-spacing runs.
+  const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns();
 
   //Takes the character index, obtains the glyph index (and the number of Glyphs) from it and finally gets the glyph metrics.
   glyphIndex     = *(charactersToGlyphBuffer + index);
@@ -122,7 +128,8 @@ void GetGlyphMetricsFromCharacterIndex(CharacterIndex         index,
 
   float calculatedAdvance = 0.f;
 
-  calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + glyphIndex)).advance);
+  const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+  calculatedAdvance            = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + glyphIndex)).advance);
 
   // Get the metrics for the group of glyphs.
   GetGlyphsMetrics(glyphIndex,
index 85676cf..db2fddf 100644 (file)
@@ -20,6 +20,7 @@
 
 // INTERNAL INCLUDE
 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
 
 namespace Dali
 {
@@ -38,13 +39,16 @@ void CalculateGlyphPositionsLTR(const VisualModelPtr&  visualModel,
                                 Vector2*               glyphPositionsBuffer,
                                 float&                 penX)
 {
-  const GlyphInfo* const glyphsBuffer     = visualModel->mGlyphs.Begin();
-  const float            characterSpacing = visualModel->GetCharacterSpacing();
-  const Character* const textBuffer       = logicalModel->mText.Begin();
+  const GlyphInfo* const glyphsBuffer          = visualModel->mGlyphs.Begin();
+  const float            modelCharacterSpacing = visualModel->GetCharacterSpacing();
+  const Character* const textBuffer            = logicalModel->mText.Begin();
 
   Vector<CharacterIndex>& glyphToCharacterMap       = visualModel->mGlyphsToCharacters;
   const CharacterIndex*   glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
 
+  // Get the character-spacing runs.
+  const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns();
+
   float calculatedAdvance = 0.f;
 
   for(GlyphIndex i = 0u; i < numberOfGlyphs; ++i)
@@ -55,7 +59,8 @@ void CalculateGlyphPositionsLTR(const VisualModelPtr&  visualModel,
     position.x = penX + glyph.xBearing;
     position.y = -glyph.yBearing;
 
-    calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + (startIndexForGlyph + i)))), characterSpacing, glyph.advance);
+    const float characterSpacing = GetGlyphCharacterSpacing((startIndexForGlyph + i), characterSpacingGlyphRuns, modelCharacterSpacing);
+    calculatedAdvance            = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + (startIndexForGlyph + i)))), characterSpacing, glyph.advance);
     penX += (calculatedAdvance + interGlyphExtraAdvance);
   }
 }
@@ -73,7 +78,10 @@ void CalculateGlyphPositionsRTL(const VisualModelPtr&            visualModel,
   const BidirectionalLineInfoRun& bidiLine                 = logicalModel->mBidirectionalLineInfo[bidiLineIndex];
   const GlyphInfo* const          glyphsBuffer             = visualModel->mGlyphs.Begin();
   const GlyphIndex* const         charactersToGlyphsBuffer = visualModel->mCharactersToGlyph.Begin();
-  const float                     characterSpacing         = visualModel->GetCharacterSpacing();
+  const float                     modelCharacterSpacing    = visualModel->GetCharacterSpacing();
+
+  // Get the character-spacing runs.
+  const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns();
 
   float calculatedAdvance = 0.f;
 
@@ -86,7 +94,8 @@ void CalculateGlyphPositionsRTL(const VisualModelPtr&            visualModel,
     position.x        = penX;
     position.y        = -glyph.yBearing;
 
-    calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyph.advance);
+    const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+    calculatedAdvance            = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyph.advance);
     penX += calculatedAdvance;
 
     ++characterLogicalIndex;
@@ -106,9 +115,12 @@ void TraversesCharactersForGlyphPositionsRTL(const VisualModelPtr&  visualModel,
 {
   const GlyphInfo* const  glyphsBuffer             = visualModel->mGlyphs.Begin();
   const GlyphIndex* const charactersToGlyphsBuffer = visualModel->mCharactersToGlyph.Begin();
-  const float             characterSpacing         = visualModel->GetCharacterSpacing();
+  const float             modelCharacterSpacing    = visualModel->GetCharacterSpacing();
   const Length* const     glyphsPerCharacterBuffer = visualModel->mGlyphsPerCharacter.Begin();
 
+  // Get the character-spacing runs.
+  const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns();
+
   float calculatedAdvance = 0.f;
 
   for(; characterLogicalIndex < bidiLineCharacterRun.numberOfCharacters;
@@ -133,7 +145,8 @@ void TraversesCharactersForGlyphPositionsRTL(const VisualModelPtr&  visualModel,
       position.x = penX + glyph.xBearing;
       position.y = -glyph.yBearing;
 
-      calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyph.advance);
+      const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+      calculatedAdvance            = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyph.advance);
       penX += (calculatedAdvance + interGlyphExtraAdvance);
     }
   }
index aff78c6..3fcc82c 100644 (file)
@@ -30,6 +30,7 @@
 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
 #include <dali-toolkit/internal/text/layouts/layout-engine-helper-functions.h>
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
 
 namespace Dali
 {
@@ -299,7 +300,10 @@ struct Engine::Impl
 
     const float      outlineWidth                = static_cast<float>(parameters.textModel->GetOutlineWidth());
     const GlyphIndex lastGlyphOfParagraphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs;
-    const float      characterSpacing            = parameters.textModel->mVisualModel->GetCharacterSpacing();
+    const float      modelCharacterSpacing       = parameters.textModel->mVisualModel->GetCharacterSpacing();
+
+    // Get the character-spacing runs.
+    const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = parameters.textModel->mVisualModel->GetCharacterSpacingGlyphRuns();
 
     CharacterIndex characterLogicalIndex = 0u;
     CharacterIndex characterVisualIndex  = 0u;
@@ -330,7 +334,8 @@ struct Engine::Impl
         {
           const GlyphInfo& glyphInfo = *(glyphsBuffer + *(charactersToGlyphsBuffer + characterVisualIndex));
 
-          calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance);
+          const float characterSpacing = GetGlyphCharacterSpacing(characterVisualIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+          calculatedAdvance            = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance);
           whiteSpaceLengthEndOfLine += calculatedAdvance;
 
           ++characterLogicalIndex;
@@ -352,7 +357,8 @@ struct Engine::Impl
         {
           const GlyphInfo& glyphInfo = *(glyphsBuffer + *(charactersToGlyphsBuffer + characterVisualIndex));
 
-          calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance);
+          const float characterSpacing = GetGlyphCharacterSpacing(characterVisualIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+          calculatedAdvance            = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance);
           whiteSpaceLengthEndOfLine += calculatedAdvance;
 
           ++characterLogicalIndex;
@@ -370,7 +376,8 @@ struct Engine::Impl
                                                                   charactersPerGlyphBuffer);
 
     GlyphMetrics glyphMetrics;
-    calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
+    const float  characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+    calculatedAdvance             = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
     GetGlyphsMetrics(glyphIndex,
                      numberOfGLyphsInGroup,
                      glyphMetrics,
@@ -401,7 +408,8 @@ struct Engine::Impl
         characterLogicalIndex += *(charactersPerGlyphBuffer + glyphIndex + numberOfGLyphsInGroup - 1u);
 
         GlyphMetrics glyphMetrics;
-        calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
+        const float  characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+        calculatedAdvance             = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
         GetGlyphsMetrics(glyphIndex,
                          numberOfGLyphsInGroup,
                          glyphMetrics,
@@ -463,7 +471,8 @@ struct Engine::Impl
       characterLogicalIndex += *(charactersPerGlyphBuffer + glyphIndex + numberOfGLyphsInGroup - 1u);
 
       GlyphMetrics glyphMetrics;
-      calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
+      const float  characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+      calculatedAdvance             = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
       GetGlyphsMetrics(glyphIndex,
                        numberOfGLyphsInGroup,
                        glyphMetrics,
@@ -700,13 +709,17 @@ struct Engine::Impl
 
     bool isSecondHalf = false;
     // Character Spacing
-    const float             characterSpacing          = parameters.textModel->mVisualModel->GetCharacterSpacing();
+    const float             modelCharacterSpacing     = parameters.textModel->mVisualModel->GetCharacterSpacing();
     float                   calculatedAdvance         = 0.f;
     Vector<CharacterIndex>& glyphToCharacterMap       = parameters.textModel->mVisualModel->mGlyphsToCharacters;
     const CharacterIndex*   glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
 
+    // Get the character-spacing runs.
+    const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = parameters.textModel->mVisualModel->GetCharacterSpacingGlyphRuns();
+
     GlyphMetrics glyphMetrics;
-    calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + lineLayout.glyphIndex))), characterSpacing, (*(glyphsBuffer + lineLayout.glyphIndex)).advance);
+    const float  characterSpacing = GetGlyphCharacterSpacing(lineLayout.glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+    calculatedAdvance             = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + lineLayout.glyphIndex))), characterSpacing, (*(glyphsBuffer + lineLayout.glyphIndex)).advance);
     GetGlyphsMetrics(lineLayout.glyphIndex,
                      numberOfGLyphsInGroup,
                      glyphMetrics,
@@ -747,7 +760,8 @@ struct Engine::Impl
                                                                     charactersPerGlyphBuffer);
 
       GlyphMetrics glyphMetrics;
-      calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
+      const float  characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+      calculatedAdvance             = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
       GetGlyphsMetrics(glyphIndex,
                        numberOfGLyphsInGroup,
                        glyphMetrics,
@@ -847,7 +861,8 @@ struct Engine::Impl
         while(tmpLineLayout.length + tmpLineLayout.whiteSpaceLengthEndOfLine > targetWidth && glyphIndexToRemove < glyphIndex)
         {
           GlyphMetrics glyphMetrics;
-          calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndexToRemove))), characterSpacing, (*(glyphsBuffer + glyphIndexToRemove)).advance);
+          const float  characterSpacing = GetGlyphCharacterSpacing(glyphIndexToRemove, characterSpacingGlyphRuns, modelCharacterSpacing);
+          calculatedAdvance             = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndexToRemove))), characterSpacing, (*(glyphsBuffer + glyphIndexToRemove)).advance);
           GetGlyphsMetrics(glyphIndexToRemove,
                            numberOfGLyphsInGroup,
                            glyphMetrics,
index 9ad00bc..7ebf2a7 100644 (file)
@@ -345,6 +345,13 @@ void LogicalModel::UpdateTextStyleRuns(CharacterIndex index, int numberOfCharact
                                            totalNumberOfCharacters,
                                            mBoundedParagraphRuns,
                                            removedBoundedParagraphRuns);
+
+  Vector<CharacterSpacingCharacterRun> removedCharacterSpacingCharacterRuns;
+  UpdateCharacterRuns<CharacterSpacingCharacterRun>(index,
+                                                    numberOfCharacters,
+                                                    totalNumberOfCharacters,
+                                                    mCharacterSpacingCharacterRuns,
+                                                    removedCharacterSpacingCharacterRuns);
 }
 
 void LogicalModel::RetrieveStyle(CharacterIndex index, InputStyle& style)
@@ -624,6 +631,16 @@ const Vector<BoundedParagraphRun>& LogicalModel::GetBoundedParagraphRuns() const
   return mBoundedParagraphRuns;
 }
 
+Length LogicalModel::GetNumberOfCharacterSpacingCharacterRuns() const
+{
+  return mCharacterSpacingCharacterRuns.Count();
+}
+
+const Vector<CharacterSpacingCharacterRun>& LogicalModel::GetCharacterSpacingCharacterRuns() const
+{
+  return mCharacterSpacingCharacterRuns;
+}
+
 void LogicalModel::ClearEmbeddedImages()
 {
   FreeEmbeddedItems(mEmbeddedItems);
index c54c523..0fa3df2 100644 (file)
@@ -28,6 +28,7 @@
 #include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
 #include <dali-toolkit/internal/text/bidirectional-paragraph-info-run.h>
 #include <dali-toolkit/internal/text/bounded-paragraph-run.h>
+#include <dali-toolkit/internal/text/character-spacing-character-run.h>
 #include <dali-toolkit/internal/text/color-run.h>
 #include <dali-toolkit/internal/text/embedded-item.h>
 #include <dali-toolkit/internal/text/font-description-run.h>
@@ -197,6 +198,20 @@ public:
    */
   const Vector<BoundedParagraphRun>& GetBoundedParagraphRuns() const;
 
+  /**
+   * @brief Retrieves the number of character-spacing runs.
+   *
+   * @return The number of character-spacing runs.
+   */
+  Length GetNumberOfCharacterSpacingCharacterRuns() const;
+
+  /**
+   * @brief Retrieves the reference for character-spacing runs.
+   *
+   * @return The reference for character-spacing runs.
+   */
+  const Vector<CharacterSpacingCharacterRun>& GetCharacterSpacingCharacterRuns() const;
+
   // Embedded images
 
   /**
@@ -241,9 +256,10 @@ public:
   Vector<BidirectionalLineInfoRun>      mBidirectionalLineInfo;
   Vector<EmbeddedItem>                  mEmbeddedItems;
   Vector<Anchor>                        mAnchors;
-  Vector<UnderlinedCharacterRun>        mUnderlinedCharacterRuns;    ///< The underlined character run from markup-processor
-  Vector<StrikethroughCharacterRun>     mStrikethroughCharacterRuns; ///< The strikethrough character run from markup-processor
-  Vector<BoundedParagraphRun>           mBoundedParagraphRuns;       ///< The bounded paragraph is used to handle a paragraph mark-up tag and it's attributes. Like TextAlign, TextDirection, TextIndent, LineHeight, etc.
+  Vector<UnderlinedCharacterRun>        mUnderlinedCharacterRuns;       ///< The underlined character run from markup-processor
+  Vector<StrikethroughCharacterRun>     mStrikethroughCharacterRuns;    ///< The strikethrough character run from markup-processor
+  Vector<BoundedParagraphRun>           mBoundedParagraphRuns;          ///< The bounded paragraph is used to handle a paragraph mark-up tag and it's attributes. Like TextAlign, TextDirection, TextIndent, LineHeight, etc.
+  Vector<CharacterSpacingCharacterRun>  mCharacterSpacingCharacterRuns; ///< The character-spacing character run from markup-processor.
 
   BidirectionalLineRunIndex mBidirectionalLineIndex; ///< The last fetched bidirectional line info.
 };
diff --git a/dali-toolkit/internal/text/markup-processor-character-spacing.cpp b/dali-toolkit/internal/text/markup-processor-character-spacing.cpp
new file mode 100644 (file)
index 0000000..f0ef362
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor-character-spacing.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#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>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace
+{
+const std::string XHTML_VALUE_ATTRIBUTE("value");
+
+} // namespace
+
+void ProcessValueAttribute(const Attribute& attribute, CharacterSpacingCharacterRun& characterSpacingCharacterRun)
+{
+  characterSpacingCharacterRun.value = ProcessFloatAttribute(attribute);
+}
+
+void ProcessCharacterSpacingTag(const Tag& tag, CharacterSpacingCharacterRun& characterSpacingCharacterRun)
+{
+  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
+                                       endIt = tag.attributes.End();
+      it != endIt;
+      ++it)
+  {
+    const Attribute& attribute(*it);
+
+    if(TokenComparison(XHTML_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessValueAttribute(attribute, characterSpacingCharacterRun);
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-character-spacing.h b/dali-toolkit/internal/text/markup-processor-character-spacing.h
new file mode 100644 (file)
index 0000000..b8b9beb
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_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.
+ *
+ */
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Tag;
+struct Attribute;
+struct CharacterSpacingCharacterRun;
+
+/**
+ * @brief Fill the character-spacing character run with the value (space or advance) attribute.
+ *
+ * @param[in] attribute the value attribute.
+ * @param[out] characterSpacingCharacterRun The underlined character run
+ */
+void ProcessValueAttribute(const Attribute& attribute, CharacterSpacingCharacterRun& characterSpacingCharacterRun);
+
+/**
+ * @brief Retrieves the character-spacing run info from the tag and sets it to the character-spacing run.
+ *
+ * @param[in] tag The character-spacing tag and its attributes.
+ * @param[in,out] characterSpacingCharacterRun The character-spacing character run
+ */
+void ProcessCharacterSpacingTag(const Tag& tag, CharacterSpacingCharacterRun& characterSpacingCharacterRun);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H
index 1b3cdc2..19810ee 100644 (file)
@@ -24,6 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/color-run.h>
 #include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/markup-processor-character-spacing.h>
 #include <dali-toolkit/internal/text/markup-processor-font.h>
 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
 #include <dali-toolkit/internal/text/markup-processor-strikethrough.h>
@@ -57,20 +58,26 @@ const std::string XHTML_UNDERLINE_DASH_WIDTH_ATTRIBUTE("u-dash-width");
 const std::string XHTML_STRIKETHROUGH_COLOR_ATTRIBUTE("s-color");
 const std::string XHTML_STRIKETHROUGH_HEIGHT_ATTRIBUTE("s-height");
 
-} // namespace
+//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.
 
-void ProcessSpanTag(const Tag&                 tag,
-                    ColorRun&                  colorRun,
-                    FontDescriptionRun&        fontRun,
-                    UnderlinedCharacterRun&    underlinedCharacterRun,
-                    ColorRun&                  backgroundColorRun,
-                    StrikethroughCharacterRun& strikethroughRun,
-                    bool&                      isColorDefined,
-                    bool&                      isFontDefined,
-                    bool&                      isUnderlinedCharacterDefined,
-                    bool&                      isBackgroundColorDefined,
-                    bool&                      isStrikethroughDefined)
+} // namespace
 
+void ProcessSpanTag(const Tag&                    tag,
+                    ColorRun&                     colorRun,
+                    FontDescriptionRun&           fontRun,
+                    UnderlinedCharacterRun&       underlinedCharacterRun,
+                    ColorRun&                     backgroundColorRun,
+                    StrikethroughCharacterRun&    strikethroughRun,
+                    CharacterSpacingCharacterRun& characterSpacingCharacterRun,
+                    bool&                         isColorDefined,
+                    bool&                         isFontDefined,
+                    bool&                         isUnderlinedCharacterDefined,
+                    bool&                         isBackgroundColorDefined,
+                    bool&                         isStrikethroughDefined,
+                    bool&                         isCharacterSpacingDefined)
 {
   for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
                                        endIt = tag.attributes.End();
@@ -149,6 +156,11 @@ void ProcessSpanTag(const Tag&                 tag,
       isStrikethroughDefined = true;
       ProcessHeightAttribute(attribute, strikethroughRun);
     }
+    else if(TokenComparison(XHTML_CHARACTER_SPACING_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isCharacterSpacingDefined = true;
+      ProcessValueAttribute(attribute, characterSpacingCharacterRun);
+    }
   }
 }
 
index 6c29554..5630fd3 100644 (file)
@@ -36,23 +36,27 @@ struct MarkupProcessData;
  * @param[out] underlinedCharacterRun the underlined character run to be filled.
  * @param[out] backgroundColorRun the background color run to be filled.
  * @param[out] strikethroughRun the strikethrough run to be filled.
+ * @param[out] characterSpacingCharacterRun the character-spacing run to be filled.
  * @param[out] isColorDefined if the span has color defined.
  * @param[out] isFontDefined if the span has font defined.
  * @param[out] isUnderlinedCharacterDefined if the span has underlined-character defined.
  * @param[out] isBackgroundColorDefined if the span has background color defined.
  * @param[out] isStrikethroughDefined if the span has strikethrough defined.
+ * @param[out] isCharacterSpacingDefined if the span has character-spacing defined.
  */
-void ProcessSpanTag(const Tag&                 tag,
-                    ColorRun&                  colorRun,
-                    FontDescriptionRun&        fontRun,
-                    UnderlinedCharacterRun&    underlinedCharacterRun,
-                    ColorRun&                  backgroundColorRun,
-                    StrikethroughCharacterRun& strikethroughRun,
-                    bool&                      isColorDefined,
-                    bool&                      isFontDefined,
-                    bool&                      isUnderlinedCharacterDefined,
-                    bool&                      isBackgroundColorDefined,
-                    bool&                      isStrikethroughDefined);
+void ProcessSpanTag(const Tag&                    tag,
+                    ColorRun&                     colorRun,
+                    FontDescriptionRun&           fontRun,
+                    UnderlinedCharacterRun&       underlinedCharacterRun,
+                    ColorRun&                     backgroundColorRun,
+                    StrikethroughCharacterRun&    strikethroughRun,
+                    CharacterSpacingCharacterRun& characterSpacingCharacterRun,
+                    bool&                         isColorDefined,
+                    bool&                         isFontDefined,
+                    bool&                         isUnderlinedCharacterDefined,
+                    bool&                         isBackgroundColorDefined,
+                    bool&                         isStrikethroughDefined,
+                    bool&                         isCharacterSpacingDefined);
 
 } // namespace Text
 
index 9c26b39..1df19ca 100644 (file)
@@ -27,6 +27,7 @@
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/markup-processor-anchor.h>
 #include <dali-toolkit/internal/text/markup-processor-background.h>
+#include <dali-toolkit/internal/text/markup-processor-character-spacing.h>
 #include <dali-toolkit/internal/text/markup-processor-color.h>
 #include <dali-toolkit/internal/text/markup-processor-embedded-item.h>
 #include <dali-toolkit/internal/text/markup-processor-font.h>
@@ -62,6 +63,7 @@ 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   = '>';
@@ -83,7 +85,8 @@ const char NEW_LINE    = 0x0A; // ASCII value of the newline.
 // Range 3 0x10000u < XHTML_DECIMAL_ENTITY_RANGE <= 0x10FFFFu
 const unsigned long XHTML_DECIMAL_ENTITY_RANGE[] = {0x0u, 0xD7FFu, 0xE000u, 0xFFFDu, 0x10000u, 0x10FFFFu};
 
-const unsigned int MAX_NUM_OF_ATTRIBUTES = 13u; ///< The span tag has the 'font-family', 'font-size' 'font-weight', 'font-width', 'font-slant','text-color', 'u-color', 'u-height','u-type','u-dash-gap', 'u-dash-width', 's-color' and 's-height' attrubutes.
+// The MAX_NUM_OF_ATTRIBUTES is the number of attributes in span tag "markup-processor-span.cpp". Because it contains the maximum number of attributes in  all tags.
+const unsigned int MAX_NUM_OF_ATTRIBUTES = 14u; ///< The span tag has the 'font-family', 'font-size' 'font-weight', 'font-width', 'font-slant','text-color', 'u-color', 'u-height','u-type','u-dash-gap', 'u-dash-width', 's-color', 's-height' and 'char-space-value' attrubutes.
 const unsigned int DEFAULT_VECTOR_SIZE   = 16u; ///< Default size of run vectors.
 
 #if defined(DEBUG_ENABLED)
@@ -143,12 +146,14 @@ struct Span
   RunIndex underlinedCharacterRunIndex;
   RunIndex backgroundColorRunIndex;
   RunIndex strikethroughCharacterRunIndex;
+  RunIndex characterSpacingCharacterRunIndex;
 
   bool isColorDefined;
   bool isFontDefined;
   bool isUnderlinedCharacterDefined;
   bool isBackgroundColorDefined;
   bool isStrikethroughDefined;
+  bool isCharacterSpacingDefined;
 };
 
 /**
@@ -202,10 +207,12 @@ void Initialize(UnderlinedCharacterRun& underlinedCharacterRun)
  */
 void Initialize(Span& span)
 {
-  span.colorRunIndex                = 0u;
-  span.isColorDefined               = false;
-  span.fontRunIndex                 = 0u;
-  span.isFontDefined                = false;
+  span.colorRunIndex  = 0u;
+  span.isColorDefined = false;
+
+  span.fontRunIndex  = 0u;
+  span.isFontDefined = false;
+
   span.underlinedCharacterRunIndex  = 0u;
   span.isUnderlinedCharacterDefined = false;
   span.backgroundColorRunIndex      = 0u;
@@ -214,6 +221,10 @@ void Initialize(Span& span)
   //strikethrough
   span.strikethroughCharacterRunIndex = 0u;
   span.isStrikethroughDefined         = false;
+
+  //characterSpacing
+  span.characterSpacingCharacterRunIndex = 0u;
+  span.isCharacterSpacingDefined         = false;
 }
 
 /**
@@ -240,6 +251,18 @@ void Initialize(BoundedParagraphRun& boundedParagraphRun)
 }
 
 /**
+ * @brief Initializes a character-spacing run to its defaults.
+ *
+ * @param[in,out] characterSpacingCharacterRun The character-spacing run to initialize.
+ */
+void Initialize(CharacterSpacingCharacterRun& characterSpacingCharacterRun)
+{
+  characterSpacingCharacterRun.characterRun.characterIndex     = 0u;
+  characterSpacingCharacterRun.characterRun.numberOfCharacters = 0u;
+  characterSpacingCharacterRun.value                           = 0.0f;
+}
+
+/**
  * @brief Splits the tag string into the tag name and its attributes.
  *
  * The attributes are stored in a vector in the tag.
@@ -738,20 +761,22 @@ void ProcessAnchorTag(
  * @param[in] tagReference The tagReference we should increment/decrement
  */
 void ProcessSpanForRun(
-  const Tag&                         spanTag,
-  StyleStack<Span>&                  spanStack,
-  Vector<ColorRun>&                  colorRuns,
-  Vector<FontDescriptionRun>&        fontRuns,
-  Vector<UnderlinedCharacterRun>&    underlinedCharacterRuns,
-  Vector<ColorRun>&                  backgroundColorRuns,
-  Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns,
-  RunIndex&                          colorRunIndex,
-  RunIndex&                          fontRunIndex,
-  RunIndex&                          underlinedCharacterRunIndex,
-  RunIndex&                          backgroundColorRunIndex,
-  RunIndex&                          strikethroughCharacterRunIndex,
-  const CharacterIndex               characterIndex,
-  int&                               tagReference)
+  const Tag&                            spanTag,
+  StyleStack<Span>&                     spanStack,
+  Vector<ColorRun>&                     colorRuns,
+  Vector<FontDescriptionRun>&           fontRuns,
+  Vector<UnderlinedCharacterRun>&       underlinedCharacterRuns,
+  Vector<ColorRun>&                     backgroundColorRuns,
+  Vector<StrikethroughCharacterRun>&    strikethroughCharacterRuns,
+  Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns,
+  RunIndex&                             colorRunIndex,
+  RunIndex&                             fontRunIndex,
+  RunIndex&                             underlinedCharacterRunIndex,
+  RunIndex&                             backgroundColorRunIndex,
+  RunIndex&                             strikethroughCharacterRunIndex,
+  RunIndex&                             characterSpacingCharacterRunIndex,
+  const CharacterIndex                  characterIndex,
+  int&                                  tagReference)
 {
   if(!spanTag.isEndTag)
   {
@@ -771,21 +796,26 @@ void ProcessSpanForRun(
     StrikethroughCharacterRun strikethroughCharacterRun;
     Initialize(strikethroughCharacterRun);
 
+    CharacterSpacingCharacterRun characterSpacingCharacterRun;
+    Initialize(characterSpacingCharacterRun);
+
     Span span;
     Initialize(span);
 
     // Fill the run with the parameters.
-    colorRun.characterRun.characterIndex                  = characterIndex;
-    fontRun.characterRun.characterIndex                   = characterIndex;
-    underlinedCharacterRun.characterRun.characterIndex    = characterIndex;
-    backgroundColorRun.characterRun.characterIndex        = characterIndex;
-    strikethroughCharacterRun.characterRun.characterIndex = characterIndex;
-
-    span.colorRunIndex                  = colorRunIndex;
-    span.fontRunIndex                   = fontRunIndex;
-    span.underlinedCharacterRunIndex    = underlinedCharacterRunIndex;
-    span.backgroundColorRunIndex        = backgroundColorRunIndex;
-    span.strikethroughCharacterRunIndex = strikethroughCharacterRunIndex;
+    colorRun.characterRun.characterIndex                     = characterIndex;
+    fontRun.characterRun.characterIndex                      = characterIndex;
+    underlinedCharacterRun.characterRun.characterIndex       = characterIndex;
+    backgroundColorRun.characterRun.characterIndex           = characterIndex;
+    strikethroughCharacterRun.characterRun.characterIndex    = characterIndex;
+    characterSpacingCharacterRun.characterRun.characterIndex = characterIndex;
+
+    span.colorRunIndex                     = colorRunIndex;
+    span.fontRunIndex                      = fontRunIndex;
+    span.underlinedCharacterRunIndex       = underlinedCharacterRunIndex;
+    span.backgroundColorRunIndex           = backgroundColorRunIndex;
+    span.strikethroughCharacterRunIndex    = strikethroughCharacterRunIndex;
+    span.characterSpacingCharacterRunIndex = characterSpacingCharacterRunIndex;
 
     ProcessSpanTag(spanTag,
                    colorRun,
@@ -793,11 +823,13 @@ void ProcessSpanForRun(
                    underlinedCharacterRun,
                    backgroundColorRun,
                    strikethroughCharacterRun,
+                   characterSpacingCharacterRun,
                    span.isColorDefined,
                    span.isFontDefined,
                    span.isUnderlinedCharacterDefined,
                    span.isBackgroundColorDefined,
-                   span.isStrikethroughDefined);
+                   span.isStrikethroughDefined,
+                   span.isCharacterSpacingDefined);
 
     // Push the span into the stack.
     spanStack.Push(span);
@@ -838,6 +870,13 @@ void ProcessSpanForRun(
       ++strikethroughCharacterRunIndex;
     }
 
+    if(span.isCharacterSpacingDefined)
+    {
+      // Push the run in the logical model.
+      characterSpacingCharacterRuns.PushBack(characterSpacingCharacterRun);
+      ++characterSpacingCharacterRunIndex;
+    }
+
     // Increase reference
     ++tagReference;
   }
@@ -878,6 +917,12 @@ void ProcessSpanForRun(
         strikethroughCharacterRun.characterRun.numberOfCharacters = characterIndex - strikethroughCharacterRun.characterRun.characterIndex;
       }
 
+      if(span.isCharacterSpacingDefined)
+      {
+        CharacterSpacingCharacterRun& characterSpacingCharacterRun   = *(characterSpacingCharacterRuns.Begin() + span.characterSpacingCharacterRunIndex);
+        characterSpacingCharacterRun.characterRun.numberOfCharacters = characterIndex - characterSpacingCharacterRun.characterRun.characterIndex;
+      }
+
       --tagReference;
     }
   }
@@ -893,6 +938,7 @@ void ProcessSpanForRun(
  * @param[in] strikethroughCharacterRunIndex The strikethroughed character run index
  * @param[in] backgroundRunIndex The background run index
  * @param[in] boundedParagraphRunIndex The bounded paragraph run index
+ * @param[in] characterSpacingCharacterRunIndex The character-spacing character run index
  *
  */
 void ResizeModelVectors(MarkupProcessData& markupProcessData,
@@ -901,7 +947,8 @@ void ResizeModelVectors(MarkupProcessData& markupProcessData,
                         const RunIndex     underlinedCharacterRunIndex,
                         const RunIndex     strikethroughCharacterRunIndex,
                         const RunIndex     backgroundRunIndex,
-                        const RunIndex     boundedParagraphRunIndex)
+                        const RunIndex     boundedParagraphRunIndex,
+                        const RunIndex     characterSpacingCharacterRunIndex)
 {
   markupProcessData.fontRuns.Resize(fontRunIndex);
   markupProcessData.colorRuns.Resize(colorRunIndex);
@@ -909,6 +956,7 @@ void ResizeModelVectors(MarkupProcessData& markupProcessData,
   markupProcessData.strikethroughCharacterRuns.Resize(strikethroughCharacterRunIndex);
   markupProcessData.backgroundColorRuns.Resize(backgroundRunIndex);
   markupProcessData.boundedParagraphRuns.Resize(boundedParagraphRunIndex);
+  markupProcessData.characterSpacingCharacterRuns.Resize(characterSpacingCharacterRunIndex);
 
 #ifdef DEBUG_ENABLED
   for(unsigned int i = 0; i < colorRunIndex; ++i)
@@ -1028,23 +1076,25 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
   StyleStack<Span> spanStack;
 
   // Points the next free position in the vector of runs.
-  RunIndex colorRunIndex                  = 0u;
-  RunIndex fontRunIndex                   = 0u;
-  RunIndex underlinedCharacterRunIndex    = 0u;
-  RunIndex backgroundRunIndex             = 0u;
-  RunIndex strikethroughCharacterRunIndex = 0u;
-  RunIndex boundedParagraphRunIndex       = 0u;
+  RunIndex colorRunIndex                     = 0u;
+  RunIndex fontRunIndex                      = 0u;
+  RunIndex underlinedCharacterRunIndex       = 0u;
+  RunIndex backgroundRunIndex                = 0u;
+  RunIndex strikethroughCharacterRunIndex    = 0u;
+  RunIndex boundedParagraphRunIndex          = 0u;
+  RunIndex characterSpacingCharacterRunIndex = 0u;
 
   // check tag reference
-  int colorTagReference      = 0u;
-  int fontTagReference       = 0u;
-  int iTagReference          = 0u;
-  int bTagReference          = 0u;
-  int uTagReference          = 0u;
-  int backgroundTagReference = 0u;
-  int spanTagReference       = 0u;
-  int sTagReference          = 0u;
-  int pTagReference          = 0u;
+  int colorTagReference            = 0u;
+  int fontTagReference             = 0u;
+  int iTagReference                = 0u;
+  int bTagReference                = 0u;
+  int uTagReference                = 0u;
+  int backgroundTagReference       = 0u;
+  int spanTagReference             = 0u;
+  int sTagReference                = 0u;
+  int pTagReference                = 0u;
+  int characterSpacingTagReference = 0u;
 
   // Give an initial default value to the model's vectors.
   markupProcessData.colorRuns.Reserve(DEFAULT_VECTOR_SIZE);
@@ -1052,6 +1102,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
   markupProcessData.underlinedCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE);
   markupProcessData.backgroundColorRuns.Reserve(DEFAULT_VECTOR_SIZE);
   markupProcessData.strikethroughCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE);
+  markupProcessData.characterSpacingCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE);
 
   // Get the mark-up string buffer.
   const char*       markupStringBuffer    = markupString.c_str();
@@ -1148,11 +1199,13 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
                           markupProcessData.underlinedCharacterRuns,
                           markupProcessData.backgroundColorRuns,
                           markupProcessData.strikethroughCharacterRuns,
+                          markupProcessData.characterSpacingCharacterRuns,
                           colorRunIndex,
                           fontRunIndex,
                           underlinedCharacterRunIndex,
                           backgroundRunIndex,
                           strikethroughCharacterRunIndex,
+                          characterSpacingCharacterRunIndex,
                           characterIndex,
                           spanTagReference);
       }
@@ -1167,6 +1220,11 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
         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))
+      {
+        ProcessTagForRun<CharacterSpacingCharacterRun>(
+          markupProcessData.characterSpacingCharacterRuns, styleStack, tag, characterIndex, characterSpacingCharacterRunIndex, characterSpacingTagReference, [](const Tag& tag, CharacterSpacingCharacterRun& run) { ProcessCharacterSpacingTag(tag, run); });
+      } // <char-spacing></char-spacing>
     }   // end if( IsTag() )
     else if(markupStringBuffer < markupStringEndBuffer)
     {
@@ -1175,7 +1233,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
   }
 
   // Resize the model's vectors.
-  ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, strikethroughCharacterRunIndex, backgroundRunIndex, boundedParagraphRunIndex);
+  ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, strikethroughCharacterRunIndex, backgroundRunIndex, boundedParagraphRunIndex, characterSpacingCharacterRunIndex);
 
   // Handle the nested tags
   OverrideNestedUnderlinedCharacterRuns(markupProcessData.underlinedCharacterRuns);
index 3ef7a2d..f751843 100644 (file)
@@ -25,6 +25,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/anchor.h>
 #include <dali-toolkit/internal/text/bounded-paragraph-run.h>
+#include <dali-toolkit/internal/text/character-spacing-character-run.h>
 #include <dali-toolkit/internal/text/color-run.h>
 #include <dali-toolkit/internal/text/embedded-item.h>
 #include <dali-toolkit/internal/text/font-description-run.h>
@@ -42,14 +43,15 @@ namespace Text
  */
 struct MarkupProcessData
 {
-  MarkupProcessData(Vector<ColorRun>&                  colorRuns,
-                    Vector<FontDescriptionRun>&        fontRuns,
-                    Vector<EmbeddedItem>&              items,
-                    Vector<Anchor>&                    anchors,
-                    Vector<UnderlinedCharacterRun>&    underlinedCharacterRuns,
-                    Vector<ColorRun>&                  backgroundColorRuns,
-                    Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns,
-                    Vector<BoundedParagraphRun>&       boundedParagraphRuns)
+  MarkupProcessData(Vector<ColorRun>&                     colorRuns,
+                    Vector<FontDescriptionRun>&           fontRuns,
+                    Vector<EmbeddedItem>&                 items,
+                    Vector<Anchor>&                       anchors,
+                    Vector<UnderlinedCharacterRun>&       underlinedCharacterRuns,
+                    Vector<ColorRun>&                     backgroundColorRuns,
+                    Vector<StrikethroughCharacterRun>&    strikethroughCharacterRuns,
+                    Vector<BoundedParagraphRun>&          boundedParagraphRuns,
+                    Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns)
   : colorRuns(colorRuns),
     fontRuns(fontRuns),
     items(items),
@@ -58,19 +60,22 @@ struct MarkupProcessData
     backgroundColorRuns(backgroundColorRuns),
     strikethroughCharacterRuns(strikethroughCharacterRuns),
     boundedParagraphRuns(boundedParagraphRuns),
+    characterSpacingCharacterRuns(characterSpacingCharacterRuns),
     markupProcessedText()
   {
   }
 
-  Vector<ColorRun>&                  colorRuns;                  ///< The color runs.
-  Vector<FontDescriptionRun>&        fontRuns;                   ///< The font description runs.
-  Vector<EmbeddedItem>&              items;                      ///< The embedded items.
-  Vector<Anchor>&                    anchors;                    ///< The anchors.
-  Vector<UnderlinedCharacterRun>&    underlinedCharacterRuns;    ///< The underlined character runs.
-  Vector<ColorRun>&                  backgroundColorRuns;        ///< The background color runs.
-  Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns; ///< The strikethrough character runs.
-  Vector<BoundedParagraphRun>&       boundedParagraphRuns;       ///< The bounded paragraph runs
-  std::string                        markupProcessedText;        ///< The mark-up string.
+  Vector<ColorRun>&                     colorRuns;                     ///< The color runs.
+  Vector<FontDescriptionRun>&           fontRuns;                      ///< The font description runs.
+  Vector<EmbeddedItem>&                 items;                         ///< The embedded items.
+  Vector<Anchor>&                       anchors;                       ///< The anchors.
+  Vector<UnderlinedCharacterRun>&       underlinedCharacterRuns;       ///< The underlined character runs.
+  Vector<ColorRun>&                     backgroundColorRuns;           ///< The background color runs.
+  Vector<StrikethroughCharacterRun>&    strikethroughCharacterRuns;    ///< The strikethrough character runs.
+  Vector<BoundedParagraphRun>&          boundedParagraphRuns;          ///< The bounded paragraph runs
+  Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns; ///< The character-spacing runs
+
+  std::string markupProcessedText; ///< The mark-up string.
 };
 
 /**
diff --git a/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.cpp b/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.cpp
new file mode 100644 (file)
index 0000000..b166c99
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace
+{
+static const Vector<CharacterSpacingGlyphRun> EMPTY_CHARACTER_SPACING_GLYPH_RUNS;
+}
+float GetGlyphCharacterSpacing(const GlyphIndex&                       index,
+                               const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns,
+                               const float                             modelCharacterSpacing)
+{
+  float characterSpacing = modelCharacterSpacing;
+  for(Vector<CharacterSpacingGlyphRun>::ConstIterator it    = characterSpacingGlyphRuns.Begin(),
+                                                      endIt = characterSpacingGlyphRuns.End();
+      it != endIt;
+      ++it)
+  {
+    const CharacterSpacingGlyphRun& run = *it;
+
+    if((run.glyphRun.glyphIndex <= index) && (index < run.glyphRun.glyphIndex + run.glyphRun.numberOfGlyphs))
+    {
+      // Retrieve the latest run to handle the nested case.
+      //TODO: Using reverse Iterator will improve performance in this loop
+      characterSpacing = run.value;
+    }
+  }
+
+  return characterSpacing;
+}
+
+const Vector<CharacterSpacingGlyphRun>& GetEmptyCharacterSpacingGlyphRuns()
+{
+  // This is needed to return a common empty vector for CharacterSpacingGlyphRun
+  return EMPTY_CHARACTER_SPACING_GLYPH_RUNS;
+}
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h b/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h
new file mode 100644 (file)
index 0000000..3865b97
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef DALI_TOOLKIT_TEXT_RENDERING_STYLES_CHARACTER_SPACING_HELPER_FUNCTIONS_H
+#define DALI_TOOLKIT_TEXT_RENDERING_STYLES_CHARACTER_SPACING_HELPER_FUNCTIONS_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/text-abstraction/font-metrics.h>
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-spacing-glyph-run.h>
+#include <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+ * @brief Check the glyph at index is had character-spacing or not then return its value. Otherwise return the model character-spacing height.
+ *
+ * @param[in] index the index of glyph.
+ * @param[in] characterSpacingGlyphRuns the character-spacing glyph runs.
+ * @param[in] modelCharacterSpacing the model character-spacing value.
+ *
+ * @return the determined character-spacing value
+ */
+float GetGlyphCharacterSpacing(const GlyphIndex&                       index,
+                               const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns,
+                               const float                             modelCharacterSpacing);
+
+/**
+ * @brief Create static empty vector and retrun it.
+ *
+ * @return The reference for the empty character-spacing glyph runs.
+ */
+const Vector<CharacterSpacingGlyphRun>& GetEmptyCharacterSpacingGlyphRuns();
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_RENDERING_STYLES_CHARACTER_SPACING_HELPER_FUNCTIONS_H
\ No newline at end of file
index 33df43d..500a081 100644 (file)
@@ -26,6 +26,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/text-controls/text-label-devel.h>
 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
 #include <dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.h>
 #include <dali-toolkit/internal/text/rendering/styles/underline-helper-functions.h>
 #include <dali-toolkit/internal/text/rendering/view-model.h>
@@ -871,9 +872,12 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth,
       }
     }
 
-    const bool  underlineEnabled     = mModel->IsUnderlineEnabled();
-    const bool  strikethroughEnabled = mModel->IsStrikethroughEnabled();
-    const float characterSpacing     = mModel->GetCharacterSpacing();
+    const bool  underlineEnabled      = mModel->IsUnderlineEnabled();
+    const bool  strikethroughEnabled  = mModel->IsStrikethroughEnabled();
+    const float modelCharacterSpacing = mModel->GetCharacterSpacing();
+
+    // Get the character-spacing runs.
+    const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = mModel->GetCharacterSpacingGlyphRuns();
 
     // Aggregate underline-style-properties from mModel
     const UnderlineStyleProperties modelUnderlineProperties{mModel->GetUnderlineType(),
@@ -1018,10 +1022,11 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth,
 
       if(addHyphen)
       {
-        GlyphInfo tempInfo = *(glyphsBuffer + elidedGlyphIndex);
-        calculatedAdvance  = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + elidedGlyphIndex))), characterSpacing, tempInfo.advance);
-        position.x         = position.x + calculatedAdvance - tempInfo.xBearing + glyphInfo->xBearing;
-        position.y         = -glyphInfo->yBearing;
+        GlyphInfo   tempInfo         = *(glyphsBuffer + elidedGlyphIndex);
+        const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+        calculatedAdvance            = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + elidedGlyphIndex))), characterSpacing, tempInfo.advance);
+        position.x                   = position.x + calculatedAdvance - tempInfo.xBearing + glyphInfo->xBearing;
+        position.y                   = -glyphInfo->yBearing;
       }
 
       if(baseline < position.y + glyphInfo->yBearing)
index 0b26e4e..f02bb95 100644 (file)
@@ -655,6 +655,16 @@ const Vector<BoundedParagraphRun>& ViewModel::GetBoundedParagraphRuns() const
   return mModel->GetBoundedParagraphRuns();
 }
 
+Length ViewModel::GetNumberOfCharacterSpacingGlyphRuns() const
+{
+  return mModel->GetNumberOfCharacterSpacingGlyphRuns();
+}
+
+const Vector<CharacterSpacingGlyphRun>& ViewModel::GetCharacterSpacingGlyphRuns() const
+{
+  return mModel->GetCharacterSpacingGlyphRuns();
+}
+
 } // namespace Text
 
 } // namespace Toolkit
index 73b7fa6..c7b0b18 100644 (file)
@@ -329,6 +329,16 @@ public:
    */
   void GetStrikethroughRuns(StrikethroughGlyphRun* strikethroughRuns, StrikethroughRunIndex index, Length numberOfRuns) const override;
 
+  /**
+   * @copydoc ModelInterface::GetNumberOfCharacterSpacingGlyphRuns()
+   */
+  Length GetNumberOfCharacterSpacingGlyphRuns() const override;
+
+  /**
+   * @copydoc ModelInterface::GetCharacterSpacingGlyphRuns()
+   */
+  const Vector<CharacterSpacingGlyphRun>& GetCharacterSpacingGlyphRuns() const override;
+
 private:
   const ModelInterface* const mModel;                           ///< Pointer to the text's model.
   Vector<GlyphInfo>           mElidedGlyphs;                    ///< Stores the glyphs of the elided text.
index a129c5e..7def7e8 100644 (file)
@@ -25,6 +25,7 @@
 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali-toolkit/internal/text/cursor-helper-functions.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
 #include <dali-toolkit/internal/text/text-view.h>
 
 namespace Dali::Toolkit::Text
@@ -98,11 +99,14 @@ Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr
     const Vector4* const    backgroundColorsBuffer       = textView.GetBackgroundColors();
     const ColorIndex* const backgroundColorIndicesBuffer = textView.GetBackgroundColorIndices();
     const Vector4&          defaultBackgroundColor       = textVisualModel->IsBackgroundEnabled() ? textVisualModel->GetBackgroundColor() : Color::TRANSPARENT;
-    const float             characterSpacing             = textVisualModel->GetCharacterSpacing();
+    const float             modelCharacterSpacing        = textVisualModel->GetCharacterSpacing();
     Vector<CharacterIndex>& glyphToCharacterMap          = textVisualModel->mGlyphsToCharacters;
     const CharacterIndex*   glyphToCharacterMapBuffer    = glyphToCharacterMap.Begin();
     float                   calculatedAdvance            = 0.f;
 
+    // Get the character-spacing runs.
+    const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = textVisualModel->GetCharacterSpacingGlyphRuns();
+
     Vector4   quad;
     uint32_t  numberOfQuads = 0u;
     Length    yLineOffset   = 0;
@@ -137,6 +141,8 @@ Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr
       // Only create quads for glyphs with a background color
       if(backgroundColor != Color::TRANSPARENT)
       {
+        const float characterSpacing = GetGlyphCharacterSpacing(i, characterSpacingGlyphRuns, modelCharacterSpacing);
+
         const Vector2 position = *(positionsBuffer + i);
         calculatedAdvance      = GetCalculatedAdvance(*(textLogicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + i))), characterSpacing, glyph.advance);
 
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 e6ec978..de18e85 100644 (file)
@@ -572,6 +572,7 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
     {
       impl.CopyUnderlinedFromLogicalToVisualModels(true);
       impl.CopyStrikethroughFromLogicalToVisualModels();
+      impl.CopyCharacterSpacingFromLogicalToVisualModels();
     }
 
     updated = true;
index e97535c..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);
     }
   }
 }
@@ -1692,6 +1693,39 @@ void Controller::Impl::CopyStrikethroughFromLogicalToVisualModels()
   }
 }
 
+void Controller::Impl::CopyCharacterSpacingFromLogicalToVisualModels()
+{
+  //CharacterSpacing character runs from markup-processor
+  const Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns = mModel->mLogicalModel->mCharacterSpacingCharacterRuns;
+  const Vector<GlyphIndex>&                   charactersToGlyph             = mModel->mVisualModel->mCharactersToGlyph;
+  const Vector<Length>&                       glyphsPerCharacter            = mModel->mVisualModel->mGlyphsPerCharacter;
+
+  mModel->mVisualModel->mCharacterSpacingRuns.Clear();
+
+  for(Vector<CharacterSpacingCharacterRun>::ConstIterator it = characterSpacingCharacterRuns.Begin(), endIt = characterSpacingCharacterRuns.End(); it != endIt; ++it)
+  {
+    const CharacterIndex& characterIndex     = it->characterRun.characterIndex;
+    const Length&         numberOfCharacters = it->characterRun.numberOfCharacters;
+
+    if(numberOfCharacters == 0)
+    {
+      continue;
+    }
+
+    CharacterSpacingGlyphRun characterSpacingGlyphRun;
+    characterSpacingGlyphRun.value                   = it->value;
+    characterSpacingGlyphRun.glyphRun.glyphIndex     = charactersToGlyph[characterIndex];
+    characterSpacingGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex];
+
+    for(Length index = 1u; index < numberOfCharacters; index++)
+    {
+      characterSpacingGlyphRun.glyphRun.numberOfGlyphs += glyphsPerCharacter[characterIndex + index];
+    }
+
+    mModel->mVisualModel->mCharacterSpacingRuns.PushBack(characterSpacingGlyphRun);
+  }
+}
+
 void Controller::Impl::SetAutoScrollEnabled(bool enable)
 {
   if(mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX)
@@ -1841,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 0757bc0..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();
@@ -961,6 +969,12 @@ private:
    */
   void CopyStrikethroughFromLogicalToVisualModels();
 
+  /**
+   * @brief Copy CharacterSpacing-Character-Runs from Logical-Model to CharacterSpacing-Glyph-Runs in Visual-Model
+   *
+   */
+  void CopyCharacterSpacingFromLogicalToVisualModels();
+
 public:
   ControlInterface*            mControlInterface;           ///< Reference to the text controller.
   EditableControlInterface*    mEditableControlInterface;   ///< Reference to the editable text controller.
@@ -1008,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 0b24bc0..35408da 100644 (file)
@@ -24,6 +24,8 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/characters-helper-functions.h>
+#include <dali-toolkit/internal/text/emoji-helper.h>
 #include <dali-toolkit/internal/text/markup-processor.h>
 #include <dali-toolkit/internal/text/text-controller-impl.h>
 #include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
@@ -92,7 +94,8 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string&
                                         logicalModel->mUnderlinedCharacterRuns,
                                         logicalModel->mBackgroundColorRuns,
                                         logicalModel->mStrikethroughCharacterRuns,
-                                        logicalModel->mBoundedParagraphRuns);
+                                        logicalModel->mBoundedParagraphRuns,
+                                        logicalModel->mCharacterSpacingCharacterRuns);
 
     Length         textSize = 0u;
     const uint8_t* utf8     = NULL;
@@ -481,6 +484,7 @@ bool Controller::TextUpdater::RemoveText(
 
   ModelPtr&        model        = impl.mModel;
   LogicalModelPtr& logicalModel = model->mLogicalModel;
+  VisualModelPtr&  visualModel  = model->mVisualModel;
 
   DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveText %p mText.Count() %d cursor %d cursorOffset %d numberOfCharacters %d\n", &controller, logicalModel->mText.Count(), eventData->mPrimaryCursorPosition, cursorOffset, numberOfCharacters);
 
@@ -498,6 +502,25 @@ bool Controller::TextUpdater::RemoveText(
       cursorIndex = eventData->mPrimaryCursorPosition + cursorOffset;
     }
 
+    //Handle Emoji clustering for cursor handling
+    // Deletion case: this is handling the deletion cases when the cursor is before or after Emoji
+    //  - Before: when use delete key and cursor is before Emoji (cursorOffset = -1)
+    //  - After: when use backspace key and cursor is after Emoji (cursorOffset = 0)
+
+    const Script script = logicalModel->GetScript(cursorIndex);
+    if((numberOfCharacters == 1u) &&
+       (IsOneOfEmojiScripts(script)))
+    {
+      //TODO: Use this clustering for Emoji cases only. This needs more testing to generalize to all scripts.
+      CharacterRun emojiClusteredCharacters = RetrieveClusteredCharactersOfCharacterIndex(visualModel, logicalModel, cursorIndex);
+      Length       actualNumberOfCharacters = emojiClusteredCharacters.numberOfCharacters;
+
+      //Set cursorIndex at the first characterIndex of clustred Emoji
+      cursorIndex = emojiClusteredCharacters.characterIndex;
+
+      numberOfCharacters = actualNumberOfCharacters;
+    }
+
     if((cursorIndex + numberOfCharacters) > currentText.Count())
     {
       numberOfCharacters = currentText.Count() - cursorIndex;
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 c7e7b98..0f2bd7b 100644 (file)
@@ -24,6 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
 #include <dali-toolkit/internal/text/bounded-paragraph-run.h>
+#include <dali-toolkit/internal/text/character-spacing-glyph-run.h>
 #include <dali-toolkit/internal/text/line-run.h>
 #include <dali-toolkit/internal/text/script-run.h>
 #include <dali-toolkit/internal/text/strikethrough-glyph-run.h>
@@ -403,6 +404,20 @@ public:
   virtual const Vector<BoundedParagraphRun>& GetBoundedParagraphRuns() const = 0;
 
   /**
+   * @brief Retrieves the number of character-spacing glyph runs.
+   *
+   * @return The number of character-spacing glyph runs.
+   */
+  virtual Length GetNumberOfCharacterSpacingGlyphRuns() const = 0;
+
+  /**
+   * @brief Retrieves the reference for character-spacing glyph runs.
+   *
+   * @return The reference for character-spacing glyph runs.
+   */
+  virtual const Vector<CharacterSpacingGlyphRun>& GetCharacterSpacingGlyphRuns() const = 0;
+
+  /**
    * @brief Retrieves the strikethrough runs.
    *
    * @param[out] strikethroughRuns Pointer to a buffer where the strikethrough runs are copied.
index 924343c..0ac67ca 100644 (file)
@@ -291,6 +291,16 @@ void Model::GetStrikethroughRuns(StrikethroughGlyphRun* strikethroughRuns, Strik
   mVisualModel->GetStrikethroughRuns(strikethroughRuns, index, numberOfRuns);
 }
 
+Length Model::GetNumberOfCharacterSpacingGlyphRuns() const
+{
+  return mVisualModel->GetNumberOfCharacterSpacingGlyphRuns();
+}
+
+const Vector<CharacterSpacingGlyphRun>& Model::GetCharacterSpacingGlyphRuns() const
+{
+  return mVisualModel->GetCharacterSpacingGlyphRuns();
+}
+
 const float Model::GetCharacterSpacing() const
 {
   return mVisualModel->GetCharacterSpacing();
index ded9496..416df17 100644 (file)
@@ -23,6 +23,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/bounded-paragraph-run.h>
+#include <dali-toolkit/internal/text/character-spacing-glyph-run.h>
 #include <dali-toolkit/internal/text/logical-model-impl.h>
 #include <dali-toolkit/internal/text/text-model-interface.h>
 #include <dali-toolkit/internal/text/visual-model-impl.h>
@@ -313,6 +314,16 @@ public:
    */
   virtual const Vector<BoundedParagraphRun>& GetBoundedParagraphRuns() const override;
 
+  /**
+   * @copydoc ModelInterface::GetNumberOfCharacterSpacingGlyphRuns()
+   */
+  Length GetNumberOfCharacterSpacingGlyphRuns() const override;
+
+  /**
+   * @copydoc ModelInterface::GetCharacterSpacingGlyphRuns()
+   */
+  const Vector<CharacterSpacingGlyphRun>& GetCharacterSpacingGlyphRuns() const override;
+
 private: // Private contructors & copy operator.
   /**
    * @brief Private constructor.
index a36f81f..05d8ad5 100644 (file)
@@ -24,6 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/cursor-helper-functions.h>
 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
 #include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
 
 using namespace Dali;
@@ -108,10 +109,13 @@ void SelectionHandleController::Reposition(Controller::Impl& impl)
   const GlyphIndex        glyphStart                = *(charactersToGlyphBuffer + selectionStart);
   const Length            numberOfGlyphs            = *(glyphsPerCharacterBuffer + selectionEndMinusOne);
   const GlyphIndex        glyphEnd                  = *(charactersToGlyphBuffer + selectionEndMinusOne) + ((numberOfGlyphs > 0) ? numberOfGlyphs - 1u : 0u);
-  const float             characterSpacing          = visualModel->GetCharacterSpacing();
+  const float             modelCharacterSpacing     = visualModel->GetCharacterSpacing();
   Vector<CharacterIndex>& glyphToCharacterMap       = visualModel->mGlyphsToCharacters;
   const CharacterIndex*   glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
 
+  // Get the character-spacing runs.
+  const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns();
+
   // Get the lines where the glyphs are laid-out.
   const LineRun* lineRun = visualModel->mLines.Begin();
 
@@ -174,9 +178,10 @@ void SelectionHandleController::Reposition(Controller::Impl& impl)
   // Traverse the glyphs.
   for(GlyphIndex index = glyphStart; index <= glyphEnd; ++index)
   {
-    const GlyphInfo& glyph    = *(glyphsBuffer + index);
-    const Vector2&   position = *(positionsBuffer + index);
-    calculatedAdvance         = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyph.advance);
+    const float      characterSpacing = GetGlyphCharacterSpacing(index, characterSpacingGlyphRuns, modelCharacterSpacing);
+    const GlyphInfo& glyph            = *(glyphsBuffer + index);
+    const Vector2&   position         = *(positionsBuffer + index);
+    calculatedAdvance                 = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyph.advance);
 
     if(splitStartGlyph)
     {
index 9caf068..98b420d 100644 (file)
@@ -24,6 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
 #include <dali-toolkit/internal/text/bounded-paragraph-run.h>
+#include <dali-toolkit/internal/text/character-spacing-glyph-run.h>
 #include <dali-toolkit/internal/text/text-definitions.h>
 #include <dali-toolkit/internal/text/underlined-glyph-run.h>
 #include <dali-toolkit/public-api/text/text-enumerations.h>
@@ -338,6 +339,20 @@ public:
   virtual const Vector<BoundedParagraphRun>& GetBoundedParagraphRuns() const = 0;
 
   /**
+   * @brief Retrieves the number of character-spacing glyph runs.
+   *
+   * @return The number of character-spacing glyph runs.
+   */
+  virtual Length GetNumberOfCharacterSpacingGlyphRuns() const = 0;
+
+  /**
+   * @brief Retrieves the reference for character-spacing glyph runs.
+   *
+   * @return The reference for character-spacing glyph runs.
+   */
+  virtual const Vector<CharacterSpacingGlyphRun>& GetCharacterSpacingGlyphRuns() const = 0;
+
+  /**
    * @brief Retrieves the strikethrough runs.
    *
    * @param[out] strikethroughRuns Pointer to a buffer where the strikethrough runs are copied.
index fdccbe1..697dc04 100644 (file)
@@ -25,6 +25,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
 
 namespace Dali
 {
@@ -107,14 +108,18 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
 {
   Length                  numberOfLaidOutGlyphs       = 0u;
   Length                  numberOfActualLaidOutGlyphs = 0u;
-  const float             characterSpacing            = mImpl->mVisualModel->GetCharacterSpacing();
+  const float             modelCharacterSpacing       = mImpl->mVisualModel->GetCharacterSpacing();
   Vector<CharacterIndex>& glyphToCharacterMap         = mImpl->mVisualModel->mGlyphsToCharacters;
   const CharacterIndex*   glyphToCharacterMapBuffer   = glyphToCharacterMap.Begin();
   float                   calculatedAdvance           = 0.f;
   const Character*        textBuffer                  = mImpl->mLogicalModel->mText.Begin();
 
+
   if(mImpl->mVisualModel)
   {
+    // Get the character-spacing runs.
+    const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = mImpl->mVisualModel->GetCharacterSpacingGlyphRuns();
+
     bool                              textElided       = false;
     DevelText::EllipsisPosition::Type ellipsisPosition = GetEllipsisPosition();
 
@@ -356,7 +361,8 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
                 firstPenSet = true;
               }
 
-              calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + indexOfEllipsis))), characterSpacing, glyphToRemove.advance);
+              const float characterSpacing = GetGlyphCharacterSpacing(indexOfEllipsis, characterSpacingGlyphRuns, modelCharacterSpacing);
+              calculatedAdvance            = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + indexOfEllipsis))), characterSpacing, glyphToRemove.advance);
               removedGlypsWidth += std::min(calculatedAdvance, (glyphToRemove.xBearing + glyphToRemove.width));
 
               // Calculate the width of the ellipsis glyph and check if it fits.
@@ -839,6 +845,16 @@ const Vector<BoundedParagraphRun>& View::GetBoundedParagraphRuns() const
   return mImpl->mLogicalModel->GetBoundedParagraphRuns();
 }
 
+Length View::GetNumberOfCharacterSpacingGlyphRuns() const
+{
+  return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetNumberOfCharacterSpacingGlyphRuns() : 0u;
+}
+
+const Vector<CharacterSpacingGlyphRun>& View::GetCharacterSpacingGlyphRuns() const
+{
+  return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetCharacterSpacingGlyphRuns() : GetEmptyCharacterSpacingGlyphRuns();
+}
+
 const float View::GetCharacterSpacing() const
 {
   return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetCharacterSpacing() : 0.f;
index 06bf838..93542cc 100644 (file)
@@ -259,6 +259,16 @@ public:
   virtual const Vector<BoundedParagraphRun>& GetBoundedParagraphRuns() const;
 
   /**
+   * @copydoc Dali::Toolkit::Text::ViewInterface::GetNumberOfCharacterSpacingGlyphRuns()
+   */
+  Length GetNumberOfCharacterSpacingGlyphRuns() const override;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::ViewInterface::GetCharacterSpacingGlyphRuns()
+   */
+  const Vector<CharacterSpacingGlyphRun>& GetCharacterSpacingGlyphRuns() const override;
+
+  /**
    * @copydoc Dali::Toolkit::Text::ViewInterface::GetCharacterSpacing()
    */
   const float GetCharacterSpacing() const override;
index ce0fb7c..5ef2b50 100644 (file)
@@ -609,6 +609,16 @@ Length VisualModel::GetNumberOfStrikethroughRuns() const
   return mStrikethroughRuns.Count();
 }
 
+Length VisualModel::GetNumberOfCharacterSpacingGlyphRuns() const
+{
+  return mCharacterSpacingRuns.Count();
+}
+
+const Vector<CharacterSpacingGlyphRun>& VisualModel::GetCharacterSpacingGlyphRuns() const
+{
+  return mCharacterSpacingRuns;
+}
+
 void VisualModel::ClearCaches()
 {
   mCachedLineIndex = 0u;
index 4bae17c..9c0af3a 100644 (file)
@@ -26,6 +26,7 @@
 #include <dali/public-api/object/ref-object.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-spacing-glyph-run.h>
 #include <dali-toolkit/internal/text/color-run.h>
 #include <dali-toolkit/internal/text/line-run.h>
 #include <dali-toolkit/internal/text/strikethrough-glyph-run.h>
@@ -596,6 +597,20 @@ public:
    */
   Length GetNumberOfStrikethroughRuns() const;
 
+  /**
+   * @brief Retrieves the number of character-spacing glyph runs.
+   *
+   * @return The number of character-spacing glyph runs.
+   */
+  Length GetNumberOfCharacterSpacingGlyphRuns() const;
+
+  /**
+   * @brief Retrieves the reference for character-spacing glyph runs.
+   *
+   * @return The reference for character-spacing glyph runs.
+   */
+  const Vector<CharacterSpacingGlyphRun>& GetCharacterSpacingGlyphRuns() const;
+
 protected:
   /**
    * @brief A reference counted object may only be deleted by calling Unreference().
@@ -615,34 +630,35 @@ private:
   VisualModel& operator=(const VisualModel& handle);
 
 public:
-  Vector<GlyphInfo>             mGlyphs;                 ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics.
-  Vector<CharacterIndex>        mGlyphsToCharacters;     ///< For each glyph, the index of the first character.
-  Vector<GlyphIndex>            mCharactersToGlyph;      ///< For each character, the index of the first glyph.
-  Vector<Length>                mCharactersPerGlyph;     ///< For each glyph, the number of characters that form the glyph.
-  Vector<Length>                mGlyphsPerCharacter;     ///< For each character, the number of glyphs that are shaped.
-  Vector<Vector2>               mGlyphPositions;         ///< For each glyph, the position.
-  Vector<LineRun>               mLines;                  ///< The laid out lines.
-  Vector<UnderlinedGlyphRun>    mUnderlineRuns;          ///< Runs of glyphs that are underlined.
-  Vector<Vector4>               mColors;                 ///< Colors of the glyphs.
-  Vector<ColorIndex>            mColorIndices;           ///< Indices to the vector of colors for each glyphs.
-  Vector<Vector4>               mBackgroundColors;       ///< Background colors of the glyphs.
-  Vector<ColorIndex>            mBackgroundColorIndices; ///< Indices to the vector of background colors for each glyphs.
-  Vector4                       mTextColor;              ///< The text color
-  Vector4                       mShadowColor;            ///< Color of drop shadow
-  Vector4                       mUnderlineColor;         ///< Color of underline
-  Vector4                       mOutlineColor;           ///< Color of outline
-  Vector4                       mBackgroundColor;        ///< Color of text background
-  Vector4                       mStrikethroughColor;     ///< Color of text background
-  Size                          mControlSize;            ///< The size of the UI control.
-  Vector2                       mShadowOffset;           ///< Offset for drop shadow, 0 indicates no shadow
-  float                         mUnderlineHeight;        ///< Fixed height for underline to override font metrics.
-  float                         mStrikethroughHeight;    ///< Fixed height for strikethrough to override font metrics.
-  Text::Underline::Type         mUnderlineType;          ///< The type of the underline.
-  float                         mDashedUnderlineWidth;   ///< The width of the dashes of the dashed underline.
-  float                         mDashedUnderlineGap;     ///< The gap between the dashes of the dashed underline.
-  float                         mShadowBlurRadius;       ///< Blur radius of shadow, 0 indicates no blur.
-  uint16_t                      mOutlineWidth;           ///< Width of outline.
-  Vector<StrikethroughGlyphRun> mStrikethroughRuns;      ///< Runs of glyphs that have strikethrough.
+  Vector<GlyphInfo>                mGlyphs;                 ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics.
+  Vector<CharacterIndex>           mGlyphsToCharacters;     ///< For each glyph, the index of the first character.
+  Vector<GlyphIndex>               mCharactersToGlyph;      ///< For each character, the index of the first glyph.
+  Vector<Length>                   mCharactersPerGlyph;     ///< For each glyph, the number of characters that form the glyph.
+  Vector<Length>                   mGlyphsPerCharacter;     ///< For each character, the number of glyphs that are shaped.
+  Vector<Vector2>                  mGlyphPositions;         ///< For each glyph, the position.
+  Vector<LineRun>                  mLines;                  ///< The laid out lines.
+  Vector<UnderlinedGlyphRun>       mUnderlineRuns;          ///< Runs of glyphs that are underlined.
+  Vector<Vector4>                  mColors;                 ///< Colors of the glyphs.
+  Vector<ColorIndex>               mColorIndices;           ///< Indices to the vector of colors for each glyphs.
+  Vector<Vector4>                  mBackgroundColors;       ///< Background colors of the glyphs.
+  Vector<ColorIndex>               mBackgroundColorIndices; ///< Indices to the vector of background colors for each glyphs.
+  Vector4                          mTextColor;              ///< The text color
+  Vector4                          mShadowColor;            ///< Color of drop shadow
+  Vector4                          mUnderlineColor;         ///< Color of underline
+  Vector4                          mOutlineColor;           ///< Color of outline
+  Vector4                          mBackgroundColor;        ///< Color of text background
+  Vector4                          mStrikethroughColor;     ///< Color of text background
+  Size                             mControlSize;            ///< The size of the UI control.
+  Vector2                          mShadowOffset;           ///< Offset for drop shadow, 0 indicates no shadow
+  float                            mUnderlineHeight;        ///< Fixed height for underline to override font metrics.
+  float                            mStrikethroughHeight;    ///< Fixed height for strikethrough to override font metrics.
+  Text::Underline::Type            mUnderlineType;          ///< The type of the underline.
+  float                            mDashedUnderlineWidth;   ///< The width of the dashes of the dashed underline.
+  float                            mDashedUnderlineGap;     ///< The gap between the dashes of the dashed underline.
+  float                            mShadowBlurRadius;       ///< Blur radius of shadow, 0 indicates no blur.
+  uint16_t                         mOutlineWidth;           ///< Width of outline.
+  Vector<StrikethroughGlyphRun>    mStrikethroughRuns;      ///< Runs of glyphs that have strikethrough.
+  Vector<CharacterSpacingGlyphRun> mCharacterSpacingRuns;   ///< Runs of glyphs that have character-spacing.
 
 private:
   Size mNaturalSize; ///< Size of the text with no line wrapping.
index f6e25ab..cb7df7b 100644 (file)
Binary files a/dali-toolkit/styles/images-common/button-down.9.png and b/dali-toolkit/styles/images-common/button-down.9.png differ
index a2e2e01..252880d 100644 (file)
Binary files a/dali-toolkit/styles/images-common/button-up.9.png and b/dali-toolkit/styles/images-common/button-up.9.png differ
index a6517b8..c5996ee 100644 (file)
Binary files a/dali-toolkit/styles/images-common/checkbox-selected-disabled.png and b/dali-toolkit/styles/images-common/checkbox-selected-disabled.png differ
index e3a8c43..91be569 100644 (file)
Binary files a/dali-toolkit/styles/images-common/checkbox-selected.png and b/dali-toolkit/styles/images-common/checkbox-selected.png differ
index 022c1cf..7aba7cf 100644 (file)
Binary files a/dali-toolkit/styles/images-common/checkbox-unselected-disabled.png and b/dali-toolkit/styles/images-common/checkbox-unselected-disabled.png differ
index 58e9390..b8a7d0d 100644 (file)
Binary files a/dali-toolkit/styles/images-common/checkbox-unselected.png and b/dali-toolkit/styles/images-common/checkbox-unselected.png differ
index 5c40e4b..4e30b7f 100644 (file)
Binary files a/dali-toolkit/styles/images-common/radio-button-selected-disabled.png and b/dali-toolkit/styles/images-common/radio-button-selected-disabled.png differ
index d49cbb5..7c3afab 100644 (file)
Binary files a/dali-toolkit/styles/images-common/radio-button-selected.png and b/dali-toolkit/styles/images-common/radio-button-selected.png differ
index 0c5fa5f..dc659f8 100644 (file)
Binary files a/dali-toolkit/styles/images-common/radio-button-unselected-disabled.png and b/dali-toolkit/styles/images-common/radio-button-unselected-disabled.png differ
index 6f647e8..65d93c6 100644 (file)
Binary files a/dali-toolkit/styles/images-common/radio-button-unselected.png and b/dali-toolkit/styles/images-common/radio-button-unselected.png differ
index 3e50c92..ea8a871 100644 (file)
@@ -169,9 +169,7 @@ cmake \
 %if 0%{?enable_debug}
       -DCMAKE_BUILD_TYPE=Debug \
 %endif
-%if 0%{?enable_trace}
       -DENABLE_TRACE=ON \
-%endif
       -DCMAKE_INSTALL_PREFIX=%{_prefix} \
       -DCMAKE_INSTALL_LIBDIR=%{_libdir} \
       -DCMAKE_INSTALL_INCLUDEDIR=%{_includedir} \