Merge "Remove dead code." into devel/master
authorjoogab yun <joogab.yun@samsung.com>
Tue, 8 Mar 2022 00:58:02 +0000 (00:58 +0000)
committerGerrit Code Review <gerrit@review>
Tue, 8 Mar 2022 00:58:02 +0000 (00:58 +0000)
39 files changed:
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls.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/utc-Dali-TextEditor.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp
dali-toolkit/devel-api/controls/control-accessible.cpp
dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h
dali-toolkit/devel-api/controls/text-controls/text-label-devel.h
dali-toolkit/devel-api/text/text-utils-devel.cpp
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/controls/control/control-data-impl.h
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-property-handler.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/text/cursor-helper-functions.cpp
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/layouts/layout-engine.h
dali-toolkit/internal/text/line-run.h
dali-toolkit/internal/text/markup-processor-span.cpp
dali-toolkit/internal/text/markup-processor-span.h
dali-toolkit/internal/text/markup-processor-underline.cpp
dali-toolkit/internal/text/markup-processor-underline.h
dali-toolkit/internal/text/markup-processor.cpp
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/rendering/styles/underline-helper-functions.cpp
dali-toolkit/internal/text/rendering/styles/underline-helper-functions.h
dali-toolkit/internal/text/rendering/text-typesetter.cpp
dali-toolkit/internal/text/text-controller-impl-event-handler.cpp
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-geometry.cpp
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/text/underline-style-properties.h
dali-toolkit/internal/visuals/visual-base-impl.cpp

index 1ed53dc..f75d224 100644 (file)
@@ -267,13 +267,13 @@ int UtcDaliControlAccessibilityHighlightable(void)
   ToolkitTestApplication application;
   auto control = Control::New();
 
-  auto noneset = control.GetProperty( DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE );
-  DALI_TEST_EQUALS( Property::NONE, noneset.GetType(), TEST_LOCATION );
+  auto highlightable = control.GetProperty<bool>(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE);
+  DALI_TEST_EQUALS(highlightable, false, TEST_LOCATION);
 
    // negative testcase - trying to set unconvertible value
-  control.SetProperty( DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, "deadbeef" );
-  noneset = control.GetProperty( DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE );
-  DALI_TEST_EQUALS( Property::NONE, noneset.GetType(), TEST_LOCATION );
+  control.SetProperty(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, "deadbeef");
+  highlightable = control.GetProperty<bool>(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE);
+  DALI_TEST_EQUALS(highlightable, false, TEST_LOCATION);
 
   auto q = Dali::Accessibility::Accessible::Get( control );
 
index e610f2f..df21268 100644 (file)
@@ -36,7 +36,7 @@ int UtcDaliControlPropertyAccessibilityTranslationDomain(void)
   auto control = Control::New();
 
   auto accessibility_translation_domain = DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN;
-  DALI_TEST_EQUALS( Property::NONE , control.GetProperty( accessibility_translation_domain ).GetType(), TEST_LOCATION );
+  DALI_TEST_EQUALS("", control.GetProperty<std::string>(accessibility_translation_domain), TEST_LOCATION);
 
   control.SetProperty( accessibility_translation_domain, "translation_domain_test_1" );
   DALI_TEST_EQUALS( "translation_domain_test_1" , control.GetProperty( accessibility_translation_domain ).Get<  std::string  >(), TEST_LOCATION );
index 99b9e03..c75f754 100644 (file)
@@ -87,12 +87,12 @@ int UtcDaliTextEditorMarkupUnderline(void)
   application.SendNotification();
   application.Render();
 
-  uint32_t expectedNumberOfUnderlinedGlyphs = 5u;
+  uint32_t expectedNumberOfUnderlineRuns = 2u;
 
   Toolkit::Internal::TextEditor& textEditorImpl        = GetImpl(textEditor);
   const Text::Length             numberOfUnderlineRuns = textEditorImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
 
-  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION);
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlineRuns, TEST_LOCATION);
 
   Vector<UnderlinedGlyphRun> underlineRuns;
   underlineRuns.Resize(numberOfUnderlineRuns);
@@ -100,12 +100,11 @@ int UtcDaliTextEditorMarkupUnderline(void)
 
   //ABC are underlined
   DALI_TEST_EQUALS(underlineRuns[0u].glyphRun.glyphIndex, 0u, TEST_LOCATION);
-  DALI_TEST_EQUALS(underlineRuns[1u].glyphRun.glyphIndex, 1u, TEST_LOCATION);
-  DALI_TEST_EQUALS(underlineRuns[2u].glyphRun.glyphIndex, 2u, TEST_LOCATION);
+  DALI_TEST_EQUALS(underlineRuns[0u].glyphRun.numberOfGlyphs, 3u, TEST_LOCATION);
 
   //GH are underlined
-  DALI_TEST_EQUALS(underlineRuns[3u].glyphRun.glyphIndex, 5u, TEST_LOCATION);
-  DALI_TEST_EQUALS(underlineRuns[4u].glyphRun.glyphIndex, 6u, TEST_LOCATION);
+  DALI_TEST_EQUALS(underlineRuns[1u].glyphRun.glyphIndex, 5u, TEST_LOCATION);
+  DALI_TEST_EQUALS(underlineRuns[1u].glyphRun.numberOfGlyphs, 2u, TEST_LOCATION);
 
   END_TEST;
 }
@@ -128,9 +127,7 @@ int UtcDaliTextEditorMarkupUnderlineAttributes(void)
     "<u height='5.0f'>ABC6</u>then"
     "<u type='dashed' dash-gap='3.0f'>ABC7</u>then"
     "<u type='dashed' dash-width='4.0f'>ABC8</u>then"
-    "<u color='blue' type='dashed' height='4.0f' dash-gap='2.0f' dash-width='3.0f'>ABC9</u>end"
-
-    ;
+    "<u color='blue' type='dashed' height='4.0f' dash-gap='2.0f' dash-width='3.0f'>ABC9</u>end";
 
   textEditor.SetProperty(TextEditor::Property::TEXT, testText);
   textEditor.SetProperty(TextEditor ::Property::ENABLE_MARKUP, true);
@@ -138,13 +135,12 @@ int UtcDaliTextEditorMarkupUnderlineAttributes(void)
   application.SendNotification();
   application.Render();
 
-  const uint32_t NUMBER_OF_CASES                  = 9u;
-  uint32_t       expectedNumberOfUnderlinedGlyphs = 36u;
+  const uint32_t expectedNumberOfUnderlineRuns = 9u;
 
   Toolkit::Internal::TextEditor& textEditorImpl        = GetImpl(textEditor);
   const Text::Length             numberOfUnderlineRuns = textEditorImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
 
-  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION);
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlineRuns, TEST_LOCATION);
 
   Vector<UnderlinedGlyphRun> underlineRuns;
   underlineRuns.Resize(numberOfUnderlineRuns);
@@ -153,20 +149,16 @@ int UtcDaliTextEditorMarkupUnderlineAttributes(void)
   struct DataOfCase
   {
     std::string              title;
-    uint32_t                 startIndex;
-    uint32_t                 endIndex;
-    GlyphIndex               startGlyphIndex;
-    GlyphIndex               endGlyphIndex;
+    GlyphIndex               glyphIndex;
+    Length                   numberOfGlyphs;
     UnderlineStyleProperties properties;
   };
   DataOfCase data[] =
     {
       //<u>ABC1</u>
       {"<u>ABC1</u>",
-       0u,
-       3u,
        5u,
-       8u,
+       4u,
        {
          Text::Underline::SOLID,
          Color::BLACK,
@@ -182,10 +174,8 @@ int UtcDaliTextEditorMarkupUnderlineAttributes(void)
 
       //<u type='solid'>ABC2</u>
       {"<u type='solid'>ABC2</u>",
-       4u,
-       7u,
        13u,
-       16u,
+       4u,
        {
          Text::Underline::SOLID,
          Color::BLACK,
@@ -201,10 +191,8 @@ int UtcDaliTextEditorMarkupUnderlineAttributes(void)
 
       //<u type='dashed'>ABC3</u>
       {"<u type='dashed'>ABC3</u>",
-       8u,
-       11u,
        21u,
-       24u,
+       4u,
        {
          Text::Underline::DASHED,
          Color::BLACK,
@@ -220,10 +208,8 @@ int UtcDaliTextEditorMarkupUnderlineAttributes(void)
 
       //<u type='double'>ABC4</u>
       {"<u type='double'>ABC4</u>",
-       12u,
-       15u,
        29u,
-       32u,
+       4u,
        {
          Text::Underline::DOUBLE,
          Color::BLACK,
@@ -239,10 +225,8 @@ int UtcDaliTextEditorMarkupUnderlineAttributes(void)
 
       //<u color='green'>ABC5</u>
       {"<u color='green'>ABC5</u>",
-       16u,
-       19u,
        37u,
-       40u,
+       4u,
        {
          Text::Underline::SOLID,
          Color::GREEN,
@@ -258,10 +242,8 @@ int UtcDaliTextEditorMarkupUnderlineAttributes(void)
 
       //<u height='5.0f'>ABC6</u>
       {"<u height='5.0f'>ABC6</u>",
-       20u,
-       23u,
        45u,
-       48u,
+       4u,
        {
          Text::Underline::SOLID,
          Color::BLACK,
@@ -277,10 +259,8 @@ int UtcDaliTextEditorMarkupUnderlineAttributes(void)
 
       //<u type='dashed' dash-gap='3.0f'>ABC7</u>
       {"<u type='dashed' dash-gap='3.0f'>ABC7</u>",
-       24u,
-       27u,
        53u,
-       56u,
+       4u,
        {
          Text::Underline::DASHED,
          Color::BLACK,
@@ -296,10 +276,8 @@ int UtcDaliTextEditorMarkupUnderlineAttributes(void)
 
       //<u type='dashed' dash-width='4.0f'>ABC8</u>
       {"<u type='dashed' dash-width='4.0f'>ABC8</u>",
-       28u,
-       31u,
        61u,
-       64u,
+       4u,
        {
          Text::Underline::DASHED,
          Color::BLACK,
@@ -315,10 +293,8 @@ int UtcDaliTextEditorMarkupUnderlineAttributes(void)
 
       //<u color='blue' type='dashed' height='4.0f' dash-gap='2.0f' dash-width='3.0f'>
       {"<u color='blue' type='dashed' height='4.0f' dash-gap='2.0f' dash-width='3.0f'>",
-       32u,
-       35u,
        69u,
-       72u,
+       4u,
        {
          Text::Underline::DASHED,
          Color::BLUE,
@@ -334,14 +310,291 @@ int UtcDaliTextEditorMarkupUnderlineAttributes(void)
 
     };
 
-  for(uint32_t i = 0; i < NUMBER_OF_CASES; i++)
+  for(uint32_t i = 0; i < expectedNumberOfUnderlineRuns; i++)
   {
     tet_infoline(data[i].title.c_str());
-    DALI_TEST_EQUALS(underlineRuns[data[i].startIndex].glyphRun.glyphIndex, data[i].startGlyphIndex, TEST_LOCATION);
-    DALI_TEST_EQUALS(underlineRuns[data[i].endIndex].glyphRun.glyphIndex, data[i].endGlyphIndex, TEST_LOCATION);
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.glyphIndex, data[i].glyphIndex, TEST_LOCATION);
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.numberOfGlyphs, data[i].numberOfGlyphs, TEST_LOCATION);
+    DALI_TEST_CHECK(data[i].properties == underlineRuns[i].properties);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliTextEditorMarkupSpanUnderline(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextEditorMarkupSpanUnderline ");
+
+  TextEditor textEditor = TextEditor::New();
+
+  application.GetScene().Add(textEditor);
+
+  std::string testText =
+    "start<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red'>ABC1</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='solid'>ABC2</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed'>ABC3</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='double'>ABC4</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-color='green'>ABC5</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-height='5.0f'>ABC6</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed' u-dash-gap='3.0f'>ABC7</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed' u-dash-width='4.0f'>ABC8</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-color='blue' u-type='dashed' u-height='4.0f' u-dash-gap='2.0f' u-dash-width='3.0f'>ABC9</span>end";
+
+  textEditor.SetProperty(TextEditor::Property::TEXT, testText);
+  textEditor.SetProperty(TextEditor ::Property::ENABLE_MARKUP, true);
+
+  application.SendNotification();
+  application.Render();
+
+  const uint32_t expectedNumberOfUnderlineRuns = 8u;
+
+  Toolkit::Internal::TextEditor& textEditorImpl        = GetImpl(textEditor);
+  const Text::Length             numberOfUnderlineRuns = textEditorImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
+
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlineRuns, TEST_LOCATION);
+
+  Vector<UnderlinedGlyphRun> underlineRuns;
+  underlineRuns.Resize(numberOfUnderlineRuns);
+  textEditorImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
+
+  struct DataOfCase
+  {
+    std::string              title;
+    GlyphIndex               glyphIndex;
+    Length                   numberOfGlyphs;
+    UnderlineStyleProperties properties;
+  };
+  DataOfCase data[] =
+    {
+      //<u type='solid'>ABC2</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='solid'>ABC2</span>",
+       13u,
+       4u,
+       {
+         Text::Underline::SOLID,
+         Color::BLACK,
+         0u,
+         1u,
+         2u,
+         true,
+         false,
+         false,
+         false,
+         false,
+       }},
+
+      //<u type='dashed'>ABC3</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed'>ABC3</span>",
+       21u,
+       4u,
+       {
+         Text::Underline::DASHED,
+         Color::BLACK,
+         0u,
+         1u,
+         2u,
+         true,
+         false,
+         false,
+         false,
+         false,
+       }},
 
-    DALI_TEST_CHECK(data[i].properties == underlineRuns[data[i].startIndex].properties);
-    DALI_TEST_CHECK(data[i].properties == underlineRuns[data[i].endIndex].properties);
+      //<u type='double'>ABC4</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='double'>ABC4</span>",
+       29u,
+       4u,
+       {
+         Text::Underline::DOUBLE,
+         Color::BLACK,
+         0u,
+         1u,
+         2u,
+         true,
+         false,
+         false,
+         false,
+         false,
+       }},
+
+      //<u color='green'>ABC5</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-color='green'>ABC5</span>",
+       37u,
+       4u,
+       {
+         Text::Underline::SOLID,
+         Color::GREEN,
+         0u,
+         1u,
+         2u,
+         false,
+         true,
+         false,
+         false,
+         false,
+       }},
+
+      //<u height='5.0f'>ABC6</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-height='5.0f'>ABC6</span>",
+       45u,
+       4u,
+       {
+         Text::Underline::SOLID,
+         Color::BLACK,
+         5u,
+         1u,
+         2u,
+         false,
+         false,
+         true,
+         false,
+         false,
+       }},
+
+      //<u type='dashed' dash-gap='3.0f'>ABC7</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed' u-dash-gap='3.0f'>ABC7</span>",
+       53u,
+       4u,
+       {
+         Text::Underline::DASHED,
+         Color::BLACK,
+         0u,
+         3u,
+         2u,
+         true,
+         false,
+         false,
+         true,
+         false,
+       }},
+
+      //<u type='dashed' dash-width='4.0f'>ABC8</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed' u-dash-width='4.0f'>ABC8</span>",
+       61u,
+       4u,
+       {
+         Text::Underline::DASHED,
+         Color::BLACK,
+         0u,
+         1u,
+         4u,
+         true,
+         false,
+         false,
+         false,
+         true,
+       }},
+
+      //<u color='blue' type='dashed' height='4.0f' dash-gap='2.0f' dash-width='3.0f'>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-color='blue' u-type='dashed' u-height='4.0f' u-dash-gap='2.0f' u-dash-width='3.0f'>ABC9</span>",
+       69u,
+       4u,
+       {
+         Text::Underline::DASHED,
+         Color::BLUE,
+         4u,
+         2u,
+         3u,
+         true,
+         true,
+         true,
+         true,
+         true,
+       }},
+
+    };
+
+  for(uint32_t i = 0; i < expectedNumberOfUnderlineRuns; i++)
+  {
+    tet_infoline(data[i].title.c_str());
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.glyphIndex, data[i].glyphIndex, TEST_LOCATION);
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.numberOfGlyphs, data[i].numberOfGlyphs, TEST_LOCATION);
+    DALI_TEST_CHECK(data[i].properties == underlineRuns[i].properties);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliTextEditorMarkupNestedUnderlineTags(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextEditorMarkupNestedUnderlineTags ");
+
+  TextEditor textEditor = TextEditor::New();
+
+  application.GetScene().Add(textEditor);
+
+  std::string testText = "start<u height='5.0f' color='green' >AB<u color='blue' >XYZ</u>CDE</u>end";
+
+  textEditor.SetProperty(TextEditor::Property::TEXT, testText);
+  textEditor.SetProperty(TextEditor ::Property::ENABLE_MARKUP, true);
+
+  application.SendNotification();
+  application.Render();
+
+  const uint32_t expectedNumberOfUnderlineRuns = 2u;
+
+  Toolkit::Internal::TextEditor& textEditorImpl        = GetImpl(textEditor);
+  const Text::Length             numberOfUnderlineRuns = textEditorImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
+
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlineRuns, TEST_LOCATION);
+
+  Vector<UnderlinedGlyphRun> underlineRuns;
+  underlineRuns.Resize(numberOfUnderlineRuns);
+  textEditorImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
+
+  struct DataOfCase
+  {
+    std::string              title;
+    GlyphIndex               glyphIndex;
+    Length                   numberOfGlyphs;
+    UnderlineStyleProperties properties;
+  };
+  DataOfCase data[] =
+    {
+      //Outter
+      {"<u height='5.0f' color='green' >AB<u color='blue' >XYZ</u>CDE</u>",
+       5u,
+       8u,
+       {
+         Text::Underline::SOLID,
+         Color::GREEN,
+         5u,
+         1u,
+         2u,
+         false,
+         true,
+         true,
+         false,
+         false,
+       }},
+
+      //Inner
+      {"<u color='blue' >XYZ</u>",
+       7u,
+       3u,
+       {
+         Text::Underline::SOLID,
+         Color::BLUE,
+         5u,
+         1u,
+         2u,
+         false,
+         true,
+         true,
+         false,
+         false,
+       }},
+
+    };
+
+  for(uint32_t i = 0; i < expectedNumberOfUnderlineRuns; i++)
+  {
+    tet_infoline(data[i].title.c_str());
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.glyphIndex, data[i].glyphIndex, TEST_LOCATION);
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.numberOfGlyphs, data[i].numberOfGlyphs, TEST_LOCATION);
+    DALI_TEST_CHECK(data[i].properties == underlineRuns[i].properties);
   }
 
   END_TEST;
index 8967f0e..b73142a 100644 (file)
@@ -169,12 +169,12 @@ int UtcDaliTextFieldMarkupUnderline(void)
   application.SendNotification();
   application.Render();
 
-  uint32_t expectedNumberOfUnderlinedGlyphs = 5u;
+  uint32_t expectedNumberOfUnderlineRuns = 2u;
 
   Toolkit::Internal::TextField& textFieldImpl         = GetImpl(textField);
   const Text::Length            numberOfUnderlineRuns = textFieldImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
 
-  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION);
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlineRuns, TEST_LOCATION);
 
   Vector<UnderlinedGlyphRun> underlineRuns;
   underlineRuns.Resize(numberOfUnderlineRuns);
@@ -182,12 +182,11 @@ int UtcDaliTextFieldMarkupUnderline(void)
 
   //ABC are underlined
   DALI_TEST_EQUALS(underlineRuns[0u].glyphRun.glyphIndex, 0u, TEST_LOCATION);
-  DALI_TEST_EQUALS(underlineRuns[1u].glyphRun.glyphIndex, 1u, TEST_LOCATION);
-  DALI_TEST_EQUALS(underlineRuns[2u].glyphRun.glyphIndex, 2u, TEST_LOCATION);
+  DALI_TEST_EQUALS(underlineRuns[0u].glyphRun.numberOfGlyphs, 3u, TEST_LOCATION);
 
   //GH are underlined
-  DALI_TEST_EQUALS(underlineRuns[3u].glyphRun.glyphIndex, 5u, TEST_LOCATION);
-  DALI_TEST_EQUALS(underlineRuns[4u].glyphRun.glyphIndex, 6u, TEST_LOCATION);
+  DALI_TEST_EQUALS(underlineRuns[1u].glyphRun.glyphIndex, 5u, TEST_LOCATION);
+  DALI_TEST_EQUALS(underlineRuns[1u].glyphRun.numberOfGlyphs, 2u, TEST_LOCATION);
 
   END_TEST;
 }
@@ -220,13 +219,12 @@ int UtcDaliTextFieldMarkupUnderlineAttributes(void)
   application.SendNotification();
   application.Render();
 
-  const uint32_t NUMBER_OF_CASES                  = 9u;
-  uint32_t       expectedNumberOfUnderlinedGlyphs = 36u;
+  const uint32_t expectedNumberOfUnderlineRuns = 9u;
 
   Toolkit::Internal::TextField& textFieldImpl         = GetImpl(textField);
   const Text::Length            numberOfUnderlineRuns = textFieldImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
 
-  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION);
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlineRuns, TEST_LOCATION);
 
   Vector<UnderlinedGlyphRun> underlineRuns;
   underlineRuns.Resize(numberOfUnderlineRuns);
@@ -235,20 +233,16 @@ int UtcDaliTextFieldMarkupUnderlineAttributes(void)
   struct DataOfCase
   {
     std::string              title;
-    uint32_t                 startIndex;
-    uint32_t                 endIndex;
-    GlyphIndex               startGlyphIndex;
-    GlyphIndex               endGlyphIndex;
+    GlyphIndex               glyphIndex;
+    Length                   numberOfGlyphs;
     UnderlineStyleProperties properties;
   };
   DataOfCase data[] =
     {
       //<u>ABC1</u>
       {"<u>ABC1</u>",
-       0u,
-       3u,
        5u,
-       8u,
+       4u,
        {
          Text::Underline::SOLID,
          Color::BLACK,
@@ -264,10 +258,8 @@ int UtcDaliTextFieldMarkupUnderlineAttributes(void)
 
       //<u type='solid'>ABC2</u>
       {"<u type='solid'>ABC2</u>",
-       4u,
-       7u,
        13u,
-       16u,
+       4u,
        {
          Text::Underline::SOLID,
          Color::BLACK,
@@ -283,10 +275,8 @@ int UtcDaliTextFieldMarkupUnderlineAttributes(void)
 
       //<u type='dashed'>ABC3</u>
       {"<u type='dashed'>ABC3</u>",
-       8u,
-       11u,
        21u,
-       24u,
+       4u,
        {
          Text::Underline::DASHED,
          Color::BLACK,
@@ -302,10 +292,8 @@ int UtcDaliTextFieldMarkupUnderlineAttributes(void)
 
       //<u type='double'>ABC4</u>
       {"<u type='double'>ABC4</u>",
-       12u,
-       15u,
        29u,
-       32u,
+       4u,
        {
          Text::Underline::DOUBLE,
          Color::BLACK,
@@ -321,10 +309,8 @@ int UtcDaliTextFieldMarkupUnderlineAttributes(void)
 
       //<u color='green'>ABC5</u>
       {"<u color='green'>ABC5</u>",
-       16u,
-       19u,
        37u,
-       40u,
+       4u,
        {
          Text::Underline::SOLID,
          Color::GREEN,
@@ -340,10 +326,8 @@ int UtcDaliTextFieldMarkupUnderlineAttributes(void)
 
       //<u height='5.0f'>ABC6</u>
       {"<u height='5.0f'>ABC6</u>",
-       20u,
-       23u,
        45u,
-       48u,
+       4u,
        {
          Text::Underline::SOLID,
          Color::BLACK,
@@ -359,10 +343,8 @@ int UtcDaliTextFieldMarkupUnderlineAttributes(void)
 
       //<u type='dashed' dash-gap='3.0f'>ABC7</u>
       {"<u type='dashed' dash-gap='3.0f'>ABC7</u>",
-       24u,
-       27u,
        53u,
-       56u,
+       4u,
        {
          Text::Underline::DASHED,
          Color::BLACK,
@@ -378,10 +360,8 @@ int UtcDaliTextFieldMarkupUnderlineAttributes(void)
 
       //<u type='dashed' dash-width='4.0f'>ABC8</u>
       {"<u type='dashed' dash-width='4.0f'>ABC8</u>",
-       28u,
-       31u,
        61u,
-       64u,
+       4u,
        {
          Text::Underline::DASHED,
          Color::BLACK,
@@ -397,10 +377,203 @@ int UtcDaliTextFieldMarkupUnderlineAttributes(void)
 
       //<u color='blue' type='dashed' height='4.0f' dash-gap='2.0f' dash-width='3.0f'>
       {"<u color='blue' type='dashed' height='4.0f' dash-gap='2.0f' dash-width='3.0f'>",
-       32u,
-       35u,
        69u,
-       72u,
+       4u,
+       {
+         Text::Underline::DASHED,
+         Color::BLUE,
+         4u,
+         2u,
+         3u,
+         true,
+         true,
+         true,
+         true,
+         true,
+       }},
+
+    };
+
+  for(uint32_t i = 0; i < expectedNumberOfUnderlineRuns; i++)
+  {
+    tet_infoline(data[i].title.c_str());
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.glyphIndex, data[i].glyphIndex, TEST_LOCATION);
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.numberOfGlyphs, data[i].numberOfGlyphs, TEST_LOCATION);
+    DALI_TEST_CHECK(data[i].properties == underlineRuns[i].properties);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliTextFieldMarkupSpanUnderline(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextFieldMarkupSpanUnderline ");
+
+  TextField textField = TextField::New();
+
+  application.GetScene().Add(textField);
+
+  std::string testText =
+    "start<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red'>ABC1</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='solid'>ABC2</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed'>ABC3</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='double'>ABC4</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-color='green'>ABC5</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-height='5.0f'>ABC6</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed' u-dash-gap='3.0f'>ABC7</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed' u-dash-width='4.0f'>ABC8</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-color='blue' u-type='dashed' u-height='4.0f' u-dash-gap='2.0f' u-dash-width='3.0f'>ABC9</span>end";
+
+  textField.SetProperty(TextField::Property::TEXT, testText);
+  textField.SetProperty(TextField ::Property::ENABLE_MARKUP, true);
+
+  application.SendNotification();
+  application.Render();
+
+  const uint32_t expectedNumberOfUnderlineRuns = 8u;
+
+  Toolkit::Internal::TextField& textFieldImpl         = GetImpl(textField);
+  const Text::Length            numberOfUnderlineRuns = textFieldImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
+
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlineRuns, TEST_LOCATION);
+
+  Vector<UnderlinedGlyphRun> underlineRuns;
+  underlineRuns.Resize(numberOfUnderlineRuns);
+  textFieldImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
+
+  struct DataOfCase
+  {
+    std::string              title;
+    GlyphIndex               glyphIndex;
+    Length                   numberOfGlyphs;
+    UnderlineStyleProperties properties;
+  };
+  DataOfCase data[] =
+    {
+      //<u type='solid'>ABC2</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='solid'>ABC2</span>",
+       13u,
+       4u,
+       {
+         Text::Underline::SOLID,
+         Color::BLACK,
+         0u,
+         1u,
+         2u,
+         true,
+         false,
+         false,
+         false,
+         false,
+       }},
+
+      //<u type='dashed'>ABC3</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed'>ABC3</span>",
+       21u,
+       4u,
+       {
+         Text::Underline::DASHED,
+         Color::BLACK,
+         0u,
+         1u,
+         2u,
+         true,
+         false,
+         false,
+         false,
+         false,
+       }},
+
+      //<u type='double'>ABC4</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='double'>ABC4</span>",
+       29u,
+       4u,
+       {
+         Text::Underline::DOUBLE,
+         Color::BLACK,
+         0u,
+         1u,
+         2u,
+         true,
+         false,
+         false,
+         false,
+         false,
+       }},
+
+      //<u color='green'>ABC5</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-color='green'>ABC5</span>",
+       37u,
+       4u,
+       {
+         Text::Underline::SOLID,
+         Color::GREEN,
+         0u,
+         1u,
+         2u,
+         false,
+         true,
+         false,
+         false,
+         false,
+       }},
+
+      //<u height='5.0f'>ABC6</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-height='5.0f'>ABC6</span>",
+       45u,
+       4u,
+       {
+         Text::Underline::SOLID,
+         Color::BLACK,
+         5u,
+         1u,
+         2u,
+         false,
+         false,
+         true,
+         false,
+         false,
+       }},
+
+      //<u type='dashed' dash-gap='3.0f'>ABC7</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed' u-dash-gap='3.0f'>ABC7</span>",
+       53u,
+       4u,
+       {
+         Text::Underline::DASHED,
+         Color::BLACK,
+         0u,
+         3u,
+         2u,
+         true,
+         false,
+         false,
+         true,
+         false,
+       }},
+
+      //<u type='dashed' dash-width='4.0f'>ABC8</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed' u-dash-width='4.0f'>ABC8</span>",
+       61u,
+       4u,
+       {
+         Text::Underline::DASHED,
+         Color::BLACK,
+         0u,
+         1u,
+         4u,
+         true,
+         false,
+         false,
+         false,
+         true,
+       }},
+
+      //<u color='blue' type='dashed' height='4.0f' dash-gap='2.0f' dash-width='3.0f'>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-color='blue' u-type='dashed' u-height='4.0f' u-dash-gap='2.0f' u-dash-width='3.0f'>ABC9</span>",
+       69u,
+       4u,
        {
          Text::Underline::DASHED,
          Color::BLUE,
@@ -416,14 +589,96 @@ int UtcDaliTextFieldMarkupUnderlineAttributes(void)
 
     };
 
-  for(uint32_t i = 0; i < NUMBER_OF_CASES; i++)
+  for(uint32_t i = 0; i < expectedNumberOfUnderlineRuns; i++)
   {
     tet_infoline(data[i].title.c_str());
-    DALI_TEST_EQUALS(underlineRuns[data[i].startIndex].glyphRun.glyphIndex, data[i].startGlyphIndex, TEST_LOCATION);
-    DALI_TEST_EQUALS(underlineRuns[data[i].endIndex].glyphRun.glyphIndex, data[i].endGlyphIndex, TEST_LOCATION);
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.glyphIndex, data[i].glyphIndex, TEST_LOCATION);
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.numberOfGlyphs, data[i].numberOfGlyphs, TEST_LOCATION);
+    DALI_TEST_CHECK(data[i].properties == underlineRuns[i].properties);
+  }
 
-    DALI_TEST_CHECK(data[i].properties == underlineRuns[data[i].startIndex].properties);
-    DALI_TEST_CHECK(data[i].properties == underlineRuns[data[i].endIndex].properties);
+  END_TEST;
+}
+
+int UtcDaliTextFieldMarkupNestedUnderlineTags(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextFieldMarkupNestedUnderlineTags ");
+
+  TextField textField = TextField::New();
+
+  application.GetScene().Add(textField);
+
+  std::string testText = "start<u height='5.0f' color='green' >AB<u color='blue' >XYZ</u>CDE</u>end";
+
+  textField.SetProperty(TextField::Property::TEXT, testText);
+  textField.SetProperty(TextField ::Property::ENABLE_MARKUP, true);
+
+  application.SendNotification();
+  application.Render();
+
+  const uint32_t expectedNumberOfUnderlineRuns = 2u;
+
+  Toolkit::Internal::TextField& textFieldImpl         = GetImpl(textField);
+  const Text::Length            numberOfUnderlineRuns = textFieldImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
+
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlineRuns, TEST_LOCATION);
+
+  Vector<UnderlinedGlyphRun> underlineRuns;
+  underlineRuns.Resize(numberOfUnderlineRuns);
+  textFieldImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
+
+  struct DataOfCase
+  {
+    std::string              title;
+    GlyphIndex               glyphIndex;
+    Length                   numberOfGlyphs;
+    UnderlineStyleProperties properties;
+  };
+  DataOfCase data[] =
+    {
+      //Outter
+      {"<u height='5.0f' color='green' >AB<u color='blue' >XYZ</u>CDE</u>",
+       5u,
+       8u,
+       {
+         Text::Underline::SOLID,
+         Color::GREEN,
+         5u,
+         1u,
+         2u,
+         false,
+         true,
+         true,
+         false,
+         false,
+       }},
+
+      //Inner
+      {"<u color='blue' >XYZ</u>",
+       7u,
+       3u,
+       {
+         Text::Underline::SOLID,
+         Color::BLUE,
+         5u,
+         1u,
+         2u,
+         false,
+         true,
+         true,
+         false,
+         false,
+       }},
+
+    };
+
+  for(uint32_t i = 0; i < expectedNumberOfUnderlineRuns; i++)
+  {
+    tet_infoline(data[i].title.c_str());
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.glyphIndex, data[i].glyphIndex, TEST_LOCATION);
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.numberOfGlyphs, data[i].numberOfGlyphs, TEST_LOCATION);
+    DALI_TEST_CHECK(data[i].properties == underlineRuns[i].properties);
   }
 
   END_TEST;
index 4259cdc..dd460f2 100644 (file)
@@ -46,12 +46,12 @@ int UtcDaliTextLabelMarkupUnderline(void)
   application.SendNotification();
   application.Render();
 
-  uint32_t expectedNumberOfUnderlinedGlyphs = 5u;
+  uint32_t expectedNumberOfUnderlineRuns = 2u;
 
   Toolkit::Internal::TextLabel& textLabelImpl         = GetImpl(textLabel);
   const Text::Length            numberOfUnderlineRuns = textLabelImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
 
-  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION);
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlineRuns, TEST_LOCATION);
 
   Vector<UnderlinedGlyphRun> underlineRuns;
   underlineRuns.Resize(numberOfUnderlineRuns);
@@ -59,12 +59,11 @@ int UtcDaliTextLabelMarkupUnderline(void)
 
   //ABC are underlined
   DALI_TEST_EQUALS(underlineRuns[0u].glyphRun.glyphIndex, 0u, TEST_LOCATION);
-  DALI_TEST_EQUALS(underlineRuns[1u].glyphRun.glyphIndex, 1u, TEST_LOCATION);
-  DALI_TEST_EQUALS(underlineRuns[2u].glyphRun.glyphIndex, 2u, TEST_LOCATION);
+  DALI_TEST_EQUALS(underlineRuns[0u].glyphRun.numberOfGlyphs, 3u, TEST_LOCATION);
 
   //GH are underlined
-  DALI_TEST_EQUALS(underlineRuns[3u].glyphRun.glyphIndex, 5u, TEST_LOCATION);
-  DALI_TEST_EQUALS(underlineRuns[4u].glyphRun.glyphIndex, 6u, TEST_LOCATION);
+  DALI_TEST_EQUALS(underlineRuns[1u].glyphRun.glyphIndex, 5u, TEST_LOCATION);
+  DALI_TEST_EQUALS(underlineRuns[1u].glyphRun.numberOfGlyphs, 2u, TEST_LOCATION);
 
   END_TEST;
 }
@@ -97,13 +96,12 @@ int UtcDaliTextLabelMarkupUnderlineAttributes(void)
   application.SendNotification();
   application.Render();
 
-  const uint32_t NUMBER_OF_CASES                  = 9u;
-  uint32_t       expectedNumberOfUnderlinedGlyphs = 36u;
+  const uint32_t expectedNumberOfUnderlineRuns = 9u;
 
   Toolkit::Internal::TextLabel& textLabelImpl         = GetImpl(textLabel);
   const Text::Length            numberOfUnderlineRuns = textLabelImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
 
-  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION);
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlineRuns, TEST_LOCATION);
 
   Vector<UnderlinedGlyphRun> underlineRuns;
   underlineRuns.Resize(numberOfUnderlineRuns);
@@ -112,20 +110,16 @@ int UtcDaliTextLabelMarkupUnderlineAttributes(void)
   struct DataOfCase
   {
     std::string              title;
-    uint32_t                 startIndex;
-    uint32_t                 endIndex;
-    GlyphIndex               startGlyphIndex;
-    GlyphIndex               endGlyphIndex;
+    GlyphIndex               glyphIndex;
+    Length                   numberOfGlyphs;
     UnderlineStyleProperties properties;
   };
   DataOfCase data[] =
     {
       //<u>ABC1</u>
       {"<u>ABC1</u>",
-       0u,
-       3u,
        5u,
-       8u,
+       4u,
        {
          Text::Underline::SOLID,
          Color::BLACK,
@@ -141,10 +135,8 @@ int UtcDaliTextLabelMarkupUnderlineAttributes(void)
 
       //<u type='solid'>ABC2</u>
       {"<u type='solid'>ABC2</u>",
-       4u,
-       7u,
        13u,
-       16u,
+       4u,
        {
          Text::Underline::SOLID,
          Color::BLACK,
@@ -160,10 +152,8 @@ int UtcDaliTextLabelMarkupUnderlineAttributes(void)
 
       //<u type='dashed'>ABC3</u>
       {"<u type='dashed'>ABC3</u>",
-       8u,
-       11u,
        21u,
-       24u,
+       4u,
        {
          Text::Underline::DASHED,
          Color::BLACK,
@@ -179,10 +169,8 @@ int UtcDaliTextLabelMarkupUnderlineAttributes(void)
 
       //<u type='double'>ABC4</u>
       {"<u type='double'>ABC4</u>",
-       12u,
-       15u,
        29u,
-       32u,
+       4u,
        {
          Text::Underline::DOUBLE,
          Color::BLACK,
@@ -198,10 +186,8 @@ int UtcDaliTextLabelMarkupUnderlineAttributes(void)
 
       //<u color='green'>ABC5</u>
       {"<u color='green'>ABC5</u>",
-       16u,
-       19u,
        37u,
-       40u,
+       4u,
        {
          Text::Underline::SOLID,
          Color::GREEN,
@@ -217,10 +203,8 @@ int UtcDaliTextLabelMarkupUnderlineAttributes(void)
 
       //<u height='5.0f'>ABC6</u>
       {"<u height='5.0f'>ABC6</u>",
-       20u,
-       23u,
        45u,
-       48u,
+       4u,
        {
          Text::Underline::SOLID,
          Color::BLACK,
@@ -236,10 +220,8 @@ int UtcDaliTextLabelMarkupUnderlineAttributes(void)
 
       //<u type='dashed' dash-gap='3.0f'>ABC7</u>
       {"<u type='dashed' dash-gap='3.0f'>ABC7</u>",
-       24u,
-       27u,
        53u,
-       56u,
+       4u,
        {
          Text::Underline::DASHED,
          Color::BLACK,
@@ -255,10 +237,8 @@ int UtcDaliTextLabelMarkupUnderlineAttributes(void)
 
       //<u type='dashed' dash-width='4.0f'>ABC8</u>
       {"<u type='dashed' dash-width='4.0f'>ABC8</u>",
-       28u,
-       31u,
        61u,
-       64u,
+       4u,
        {
          Text::Underline::DASHED,
          Color::BLACK,
@@ -274,10 +254,203 @@ int UtcDaliTextLabelMarkupUnderlineAttributes(void)
 
       //<u color='blue' type='dashed' height='4.0f' dash-gap='2.0f' dash-width='3.0f'>
       {"<u color='blue' type='dashed' height='4.0f' dash-gap='2.0f' dash-width='3.0f'>",
-       32u,
-       35u,
        69u,
-       72u,
+       4u,
+       {
+         Text::Underline::DASHED,
+         Color::BLUE,
+         4u,
+         2u,
+         3u,
+         true,
+         true,
+         true,
+         true,
+         true,
+       }},
+
+    };
+
+  for(uint32_t i = 0; i < expectedNumberOfUnderlineRuns; i++)
+  {
+    tet_infoline(data[i].title.c_str());
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.glyphIndex, data[i].glyphIndex, TEST_LOCATION);
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.numberOfGlyphs, data[i].numberOfGlyphs, TEST_LOCATION);
+    DALI_TEST_CHECK(data[i].properties == underlineRuns[i].properties);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliTextLabelMarkupSpanUnderline(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLabelMarkupSpanUnderline ");
+
+  TextLabel textLabel = TextLabel::New();
+
+  application.GetScene().Add(textLabel);
+
+  std::string testText =
+    "start<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red'>ABC1</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='solid'>ABC2</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed'>ABC3</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='double'>ABC4</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-color='green'>ABC5</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-height='5.0f'>ABC6</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed' u-dash-gap='3.0f'>ABC7</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed' u-dash-width='4.0f'>ABC8</span>then"
+    "<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-color='blue' u-type='dashed' u-height='4.0f' u-dash-gap='2.0f' u-dash-width='3.0f'>ABC9</span>end";
+
+  textLabel.SetProperty(TextLabel::Property::TEXT, testText);
+  textLabel.SetProperty(TextLabel ::Property::ENABLE_MARKUP, true);
+
+  application.SendNotification();
+  application.Render();
+
+  const uint32_t expectedNumberOfUnderlineRuns = 8u;
+
+  Toolkit::Internal::TextLabel& textLabelImpl         = GetImpl(textLabel);
+  const Text::Length            numberOfUnderlineRuns = textLabelImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
+
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlineRuns, TEST_LOCATION);
+
+  Vector<UnderlinedGlyphRun> underlineRuns;
+  underlineRuns.Resize(numberOfUnderlineRuns);
+  textLabelImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
+
+  struct DataOfCase
+  {
+    std::string              title;
+    GlyphIndex               glyphIndex;
+    Length                   numberOfGlyphs;
+    UnderlineStyleProperties properties;
+  };
+  DataOfCase data[] =
+    {
+      //<u type='solid'>ABC2</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='solid'>ABC2</span>",
+       13u,
+       4u,
+       {
+         Text::Underline::SOLID,
+         Color::BLACK,
+         0u,
+         1u,
+         2u,
+         true,
+         false,
+         false,
+         false,
+         false,
+       }},
+
+      //<u type='dashed'>ABC3</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed'>ABC3</span>",
+       21u,
+       4u,
+       {
+         Text::Underline::DASHED,
+         Color::BLACK,
+         0u,
+         1u,
+         2u,
+         true,
+         false,
+         false,
+         false,
+         false,
+       }},
+
+      //<u type='double'>ABC4</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='double'>ABC4</span>",
+       29u,
+       4u,
+       {
+         Text::Underline::DOUBLE,
+         Color::BLACK,
+         0u,
+         1u,
+         2u,
+         true,
+         false,
+         false,
+         false,
+         false,
+       }},
+
+      //<u color='green'>ABC5</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-color='green'>ABC5</span>",
+       37u,
+       4u,
+       {
+         Text::Underline::SOLID,
+         Color::GREEN,
+         0u,
+         1u,
+         2u,
+         false,
+         true,
+         false,
+         false,
+         false,
+       }},
+
+      //<u height='5.0f'>ABC6</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-height='5.0f'>ABC6</span>",
+       45u,
+       4u,
+       {
+         Text::Underline::SOLID,
+         Color::BLACK,
+         5u,
+         1u,
+         2u,
+         false,
+         false,
+         true,
+         false,
+         false,
+       }},
+
+      //<u type='dashed' dash-gap='3.0f'>ABC7</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed' u-dash-gap='3.0f'>ABC7</span>",
+       53u,
+       4u,
+       {
+         Text::Underline::DASHED,
+         Color::BLACK,
+         0u,
+         3u,
+         2u,
+         true,
+         false,
+         false,
+         true,
+         false,
+       }},
+
+      //<u type='dashed' dash-width='4.0f'>ABC8</u>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-type='dashed' u-dash-width='4.0f'>ABC8</span>",
+       61u,
+       4u,
+       {
+         Text::Underline::DASHED,
+         Color::BLACK,
+         0u,
+         1u,
+         4u,
+         true,
+         false,
+         false,
+         false,
+         true,
+       }},
+
+      //<u color='blue' type='dashed' height='4.0f' dash-gap='2.0f' dash-width='3.0f'>
+      {"<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' u-color='blue' u-type='dashed' u-height='4.0f' u-dash-gap='2.0f' u-dash-width='3.0f'>ABC9</span>",
+       69u,
+       4u,
        {
          Text::Underline::DASHED,
          Color::BLUE,
@@ -293,14 +466,96 @@ int UtcDaliTextLabelMarkupUnderlineAttributes(void)
 
     };
 
-  for(uint32_t i = 0; i < NUMBER_OF_CASES; i++)
+  for(uint32_t i = 0; i < expectedNumberOfUnderlineRuns; i++)
   {
     tet_infoline(data[i].title.c_str());
-    DALI_TEST_EQUALS(underlineRuns[data[i].startIndex].glyphRun.glyphIndex, data[i].startGlyphIndex, TEST_LOCATION);
-    DALI_TEST_EQUALS(underlineRuns[data[i].endIndex].glyphRun.glyphIndex, data[i].endGlyphIndex, TEST_LOCATION);
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.glyphIndex, data[i].glyphIndex, TEST_LOCATION);
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.numberOfGlyphs, data[i].numberOfGlyphs, TEST_LOCATION);
+    DALI_TEST_CHECK(data[i].properties == underlineRuns[i].properties);
+  }
 
-    DALI_TEST_CHECK(data[i].properties == underlineRuns[data[i].startIndex].properties);
-    DALI_TEST_CHECK(data[i].properties == underlineRuns[data[i].endIndex].properties);
+  END_TEST;
+}
+
+int UtcDaliTextLabelMarkupNestedUnderlineTags(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLabelMarkupNestedUnderlineTags ");
+
+  TextLabel textLabel = TextLabel::New();
+
+  application.GetScene().Add(textLabel);
+
+  std::string testText = "start<u height='5.0f' color='green' >AB<u color='blue' >XYZ</u>CDE</u>end";
+
+  textLabel.SetProperty(TextLabel::Property::TEXT, testText);
+  textLabel.SetProperty(TextLabel ::Property::ENABLE_MARKUP, true);
+
+  application.SendNotification();
+  application.Render();
+
+  const uint32_t expectedNumberOfUnderlineRuns = 2u;
+
+  Toolkit::Internal::TextLabel& textLabelImpl         = GetImpl(textLabel);
+  const Text::Length            numberOfUnderlineRuns = textLabelImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
+
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlineRuns, TEST_LOCATION);
+
+  Vector<UnderlinedGlyphRun> underlineRuns;
+  underlineRuns.Resize(numberOfUnderlineRuns);
+  textLabelImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
+
+  struct DataOfCase
+  {
+    std::string              title;
+    GlyphIndex               glyphIndex;
+    Length                   numberOfGlyphs;
+    UnderlineStyleProperties properties;
+  };
+  DataOfCase data[] =
+    {
+      //Outter
+      {"<u height='5.0f' color='green' >AB<u color='blue' >XYZ</u>CDE</u>",
+       5u,
+       8u,
+       {
+         Text::Underline::SOLID,
+         Color::GREEN,
+         5u,
+         1u,
+         2u,
+         false,
+         true,
+         true,
+         false,
+         false,
+       }},
+
+      //Inner
+      {"<u color='blue' >XYZ</u>",
+       7u,
+       3u,
+       {
+         Text::Underline::SOLID,
+         Color::BLUE,
+         5u,
+         1u,
+         2u,
+         false,
+         true,
+         true,
+         false,
+         false,
+       }},
+
+    };
+
+  for(uint32_t i = 0; i < expectedNumberOfUnderlineRuns; i++)
+  {
+    tet_infoline(data[i].title.c_str());
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.glyphIndex, data[i].glyphIndex, TEST_LOCATION);
+    DALI_TEST_EQUALS(underlineRuns[i].glyphRun.numberOfGlyphs, data[i].numberOfGlyphs, TEST_LOCATION);
+    DALI_TEST_CHECK(data[i].properties == underlineRuns[i].properties);
   }
 
   END_TEST;
index 0c3ab82..0524d55 100644 (file)
@@ -5765,6 +5765,42 @@ int UtcDaliToolkitTextEditorUnderlineTypesGeneration3(void)
   END_TEST;
 }
 
+int UtcDaliToolkitTextEditorRelativeLineHeight(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextEditorRelativeLineHeight");
+
+  TextEditor editor = TextEditor::New();
+  editor.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+  editor.SetProperty(TextEditor::Property::POINT_SIZE, 10);
+  editor.SetProperty(TextEditor::Property::TEXT, "Hello\nWorld");
+
+  application.GetScene().Add(editor);
+  application.SendNotification();
+  application.Render();
+
+  Vector3 naturalSize = editor.GetNaturalSize();
+
+  editor.SetProperty(DevelTextEditor::Property::RELATIVE_LINE_SIZE, 0.5f);
+
+  application.SendNotification();
+  application.Render();
+
+  Vector3 relativeNaturalSize = editor.GetNaturalSize();
+
+  DALI_TEST_EQUALS(naturalSize.y, relativeNaturalSize.y, TEST_LOCATION);
+
+  editor.SetProperty(DevelTextEditor::Property::RELATIVE_LINE_SIZE, 2.0f);
+
+  application.SendNotification();
+  application.Render();
+
+  relativeNaturalSize = editor.GetNaturalSize();
+
+  DALI_TEST_EQUALS(naturalSize.y * 2, relativeNaturalSize.y, TEST_LOCATION);
+  END_TEST;
+}
+
 int UtcDaliTextEditorCharacterSpacing(void)
 {
   ToolkitTestApplication application;
@@ -5788,6 +5824,39 @@ int UtcDaliTextEditorCharacterSpacing(void)
   END_TEST;
 }
 
+int UtcDaliTextEditorTextSizeNegativeLineSpacing(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliTextEditorTextSizeNegativeLineSpacing");
+
+  TextEditor editor = TextEditor::New();
+
+  float lineSpacing = -20.f;
+
+  editor.SetProperty(Actor::Property::SIZE, Vector2(450.0f, 300.f));
+  editor.SetProperty(TextEditor::Property::POINT_SIZE, 10.f);
+  editor.SetProperty(DevelTextEditor::Property::LINE_SPACING, lineSpacing);
+  editor.SetProperty(TextEditor::Property::TEXT, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
+
+  application.GetScene().Add(editor);
+  application.SendNotification();
+  application.Render();
+
+  Vector<Vector2> positionsList = DevelTextEditor::GetTextPosition(editor, 0, 123);
+  Vector<Vector2> sizeList      = DevelTextEditor::GetTextSize(editor, 0, 123);
+
+  Vector2 lastLinePos  = positionsList[positionsList.Size() - 1];
+  Vector2 lastLineSize = sizeList[sizeList.Size() - 1];
+
+  DALI_TEST_EQUALS(sizeList[0].y * (sizeList.Size() - 1), lastLinePos.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  DALI_TEST_EQUALS(sizeList[0].y - lineSpacing, lastLineSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  END_TEST;
+}
+
 int UtcDaliToolkitTexteditorParagraphTag(void)
 {
   ToolkitTestApplication application;
index ecc5f67..e12ce04 100644 (file)
@@ -2632,6 +2632,42 @@ int UtcDaliToolkitTextLabelStrikethroughGeneration(void)
   END_TEST;
 }
 
+int UtcDaliToolkitTextLabelRelativeLineHeight(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextLabelRelativeLineHeight");
+
+  TextLabel label = TextLabel::New();
+  label.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+  label.SetProperty(TextLabel::Property::POINT_SIZE, 10);
+  label.SetProperty(TextLabel::Property::TEXT, "Hello\nWorld");
+
+  application.GetScene().Add(label);
+  application.SendNotification();
+  application.Render();
+
+  Vector3 naturalSize = label.GetNaturalSize();
+
+  label.SetProperty(DevelTextLabel::Property::RELATIVE_LINE_SIZE, 0.5f);
+
+  application.SendNotification();
+  application.Render();
+
+  Vector3 relativeNaturalSize = label.GetNaturalSize();
+
+  DALI_TEST_EQUALS(naturalSize.y, relativeNaturalSize.y, TEST_LOCATION);
+
+  label.SetProperty(DevelTextLabel::Property::RELATIVE_LINE_SIZE, 2.0f);
+
+  application.SendNotification();
+  application.Render();
+
+  relativeNaturalSize = label.GetNaturalSize();
+
+  DALI_TEST_EQUALS(naturalSize.y * 2, relativeNaturalSize.y, TEST_LOCATION);
+  END_TEST;
+}
+
 int UtcDaliTextLabelCharacterSpacing(void)
 {
   ToolkitTestApplication application;
@@ -2655,6 +2691,40 @@ int UtcDaliTextLabelCharacterSpacing(void)
   END_TEST;
 }
 
+int UtcDaliTextTextLabelSizeNegativeLineSpacing(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliTextTextLabelSizeNegativeLineSpacing");
+
+  TextLabel label = TextLabel::New();
+
+  float lineSpacing = -20.f;
+
+  label.SetProperty(Actor::Property::SIZE, Vector2(450.0f, 300.f));
+  label.SetProperty(TextLabel::Property::POINT_SIZE, 10.f);
+  label.SetProperty(DevelTextLabel::Property::LINE_SPACING, lineSpacing);
+  label.SetProperty(TextLabel::Property::MULTI_LINE, true);
+  label.SetProperty(TextLabel::Property::TEXT, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
+
+  application.GetScene().Add(label);
+  application.SendNotification();
+  application.Render();
+
+  Vector<Vector2> positionsList = DevelTextLabel::GetTextPosition(label, 0, 123);
+  Vector<Vector2> sizeList      = DevelTextLabel::GetTextSize(label, 0, 123);
+
+  Vector2 lastLinePos  = positionsList[positionsList.Size() - 1];
+  Vector2 lastLineSize = sizeList[sizeList.Size() - 1];
+
+  DALI_TEST_EQUALS(sizeList[0].y * (sizeList.Size() - 1), lastLinePos.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  DALI_TEST_EQUALS(sizeList[0].y - lineSpacing, lastLineSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  END_TEST;
+}
+
 int UtcDaliToolkitTextlabelParagraphTag(void)
 {
   ToolkitTestApplication application;
index 87701b2..aaedd55 100644 (file)
@@ -6110,4 +6110,156 @@ int UtcDaliVisualUpdatePropertyChangeShader03(void)
   DALI_TEST_CHECK( !(callStack.FindMethod("CreateShader")) );
 
   END_TEST;
-}
\ No newline at end of file
+}
+
+int UtcDaliVisualUpdatePropertyChangeShader04(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliVisualUpdatePropertyChangeShader04: Test update property by DoAction during Animation. Change the shader case" );
+
+  TraceCallStack& callStack = application.GetGraphicsController().mCallStack;
+
+  VisualFactory factory = VisualFactory::Get();
+  Property::Map propertyMap;
+  // Case ImageVisual
+  propertyMap[Visual::Property::TYPE] = Visual::Type::IMAGE;
+  propertyMap[ImageVisual::Property::URL] = TEST_IMAGE_FILE_NAME;
+  propertyMap[DevelVisual::Property::CORNER_RADIUS] = 10.0f;
+
+  Visual::Base imageVisual = factory.CreateVisual(propertyMap);
+
+  DummyControl dummyControl = DummyControl::New(true);
+  Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+  dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, imageVisual);
+  dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f);
+  application.GetScene().Add(dummyControl);
+
+  application.SendNotification();
+  application.Render();
+
+  // Wait for image loading
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  // Get shader
+  {
+    Renderer renderer = dummyControl.GetRendererAt( 0 );
+    Shader shader = renderer.GetShader();
+    Property::Value value = shader.GetProperty( Shader::Property::PROGRAM );
+    Property::Map* map = value.GetMap();
+    DALI_TEST_CHECK( map );
+
+    Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+    DALI_TEST_CHECK( fragment );
+    std::string fragmentShader;
+    DALI_TEST_CHECK( fragment->Get(fragmentShader) );
+    DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+    DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+
+    Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+    std::string vertexShader;
+    DALI_TEST_CHECK( vertex->Get(vertexShader) );
+    DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+    DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+  }
+  callStack.Reset();
+  callStack.Enable(true);
+
+  Vector4 targetCornerRadius = Vector4(0.0f, 0.0f, 0.0f, 0.0f);
+
+  Animation animation = Animation::New(1.0f);
+  animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::CORNER_RADIUS), targetCornerRadius);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render();
+  application.Render(1001u); // End of animation
+
+  // Get shader
+  {
+    Renderer renderer = dummyControl.GetRendererAt( 0 );
+    Shader shader = renderer.GetShader();
+    Property::Value value = shader.GetProperty( Shader::Property::PROGRAM );
+    Property::Map* map = value.GetMap();
+    DALI_TEST_CHECK( map );
+
+    Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+    DALI_TEST_CHECK( fragment );
+    std::string fragmentShader;
+    DALI_TEST_CHECK( fragment->Get(fragmentShader) );
+    DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+    // Note : mAlwaysUsingCornerRadius is true.
+    DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+
+    Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+    std::string vertexShader;
+    DALI_TEST_CHECK( vertex->Get(vertexShader) );
+    DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+    // Note : mAlwaysUsingCornerRadius is true.
+    DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+  }
+  callStack.Enable(false);
+  // Shader not changed
+  DALI_TEST_CHECK( !callStack.FindMethod("CreateShader") );
+  callStack.Reset();
+  callStack.Enable(true);
+
+  float         targetBorderlineWidth = 10.0f;
+  Property::Map targetPropertyMap;
+  targetPropertyMap[DevelVisual::Property::BORDERLINE_WIDTH] = targetBorderlineWidth;
+
+  // Update Properties with CornerRadius
+  DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Action::UPDATE_PROPERTY, targetPropertyMap);
+
+  Property::Map resultMap;
+  imageVisual.CreatePropertyMap( resultMap );
+
+  // Test property values: they should be updated
+  Property::Value* cornerRadiusValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4);
+  DALI_TEST_CHECK(cornerRadiusValue);
+  DALI_TEST_EQUALS(cornerRadiusValue->Get<Vector4>(), targetCornerRadius, TEST_LOCATION);
+
+  Property::Value* cornerRadiusPolicyValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS_POLICY, Property::INTEGER);
+  DALI_TEST_CHECK(cornerRadiusPolicyValue);
+  DALI_TEST_EQUALS(cornerRadiusPolicyValue->Get<int>(), static_cast<int>(Toolkit::Visual::Transform::Policy::ABSOLUTE), TEST_LOCATION);
+
+  Property::Value* borderlineWidthValue = resultMap.Find(DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT);
+  DALI_TEST_CHECK(borderlineWidthValue);
+  DALI_TEST_EQUALS(borderlineWidthValue->Get<float>(), targetBorderlineWidth, TEST_LOCATION);
+
+  // Get shader
+  {
+    Renderer renderer = dummyControl.GetRendererAt( 0 );
+    Shader shader = renderer.GetShader();
+    Property::Value value = shader.GetProperty( Shader::Property::PROGRAM );
+    Property::Map* map = value.GetMap();
+    DALI_TEST_CHECK( map );
+
+    Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+    DALI_TEST_CHECK( fragment );
+    std::string fragmentShader;
+    DALI_TEST_CHECK( fragment->Get(fragmentShader) );
+    DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") != std::string::npos );
+    // Note : mAlwaysUsingCornerRadius is true.
+    DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+
+    Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+    std::string vertexShader;
+    DALI_TEST_CHECK( vertex->Get(vertexShader) );
+    DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") != std::string::npos );
+    // Note : mAlwaysUsingCornerRadius is true.
+    DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+  }
+
+  // Send shader compile signal
+  application.SendNotification();
+  application.Render();
+
+  callStack.Enable(false);
+  // Shader changed
+  DALI_TEST_CHECK( callStack.FindMethod("CreateShader") );
+
+  END_TEST;
+}
index 21fc8e2..ae7eff0 100644 (file)
@@ -85,7 +85,7 @@ ControlAccessible::ControlAccessible(Dali::Actor self, Dali::Accessibility::Role
       return;
     }
 
-    if(index == DevelControl::Property::ACCESSIBILITY_NAME || (index == GetNamePropertyIndex() && !controlImpl.mAccessibilityNameSet))
+    if(index == DevelControl::Property::ACCESSIBILITY_NAME || (index == GetNamePropertyIndex() && controlImpl.mAccessibilityName.empty()))
     {
       if(controlImpl.mAccessibilityGetNameSignal.Empty())
       {
@@ -93,7 +93,7 @@ ControlAccessible::ControlAccessible(Dali::Actor self, Dali::Accessibility::Role
       }
     }
 
-    if(index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION || (index == GetDescriptionPropertyIndex() && !controlImpl.mAccessibilityDescriptionSet))
+    if(index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION || (index == GetDescriptionPropertyIndex() && controlImpl.mAccessibilityDescription.empty()))
     {
       if(controlImpl.mAccessibilityGetDescriptionSignal.Empty())
       {
@@ -115,7 +115,7 @@ std::string ControlAccessible::GetName() const
   {
     controlImpl.mAccessibilityGetNameSignal.Emit(name);
   }
-  else if(controlImpl.mAccessibilityNameSet)
+  else if(!controlImpl.mAccessibilityName.empty())
   {
     name = controlImpl.mAccessibilityName;
   }
@@ -128,7 +128,7 @@ std::string ControlAccessible::GetName() const
     name = Self().GetProperty<std::string>(Actor::Property::NAME);
   }
 
-  if(controlImpl.mAccessibilityTranslationDomainSet)
+  if(!controlImpl.mAccessibilityTranslationDomain.empty())
   {
     return GetLocaleText(name, controlImpl.mAccessibilityTranslationDomain.c_str());
   }
@@ -153,7 +153,7 @@ std::string ControlAccessible::GetDescription() const
   {
     controlImpl.mAccessibilityGetDescriptionSignal.Emit(description);
   }
-  else if(controlImpl.mAccessibilityDescriptionSet)
+  else if(!controlImpl.mAccessibilityDescription.empty())
   {
     description = controlImpl.mAccessibilityDescription;
   }
@@ -161,7 +161,8 @@ std::string ControlAccessible::GetDescription() const
   {
     description = GetDescriptionRaw();
   }
-  if(controlImpl.mAccessibilityTranslationDomainSet)
+
+  if(!controlImpl.mAccessibilityTranslationDomain.empty())
   {
     return GetLocaleText(description, controlImpl.mAccessibilityTranslationDomain.c_str());
   }
index 8ca9648..b990dc7 100644 (file)
@@ -303,6 +303,13 @@ enum Type
   *   The default value is 0.f which does nothing.
   */
   CHARACTER_SPACING,
+
+  /**
+   * @brief the relative height of the line (a factor that will be multiplied by text height).
+   * @details Name "relativeLineSize", type Property::FLOAT.
+   * @note If the value is less than 1, the lines could to be overlapped.
+   */
+  RELATIVE_LINE_SIZE,
 };
 
 } // namespace Property
index 205950c..326d8d0 100644 (file)
@@ -194,6 +194,13 @@ enum Type
   *   The default value is 0.f which does nothing.
   */
   CHARACTER_SPACING,
+
+  /**
+   * @brief the relative height of the line (a factor that will be multiplied by text height).
+   * @details Name "relativeLineSize", type Property::FLOAT.
+   * @note If the value is less than 1, the lines could to be overlapped.
+   */
+  RELATIVE_LINE_SIZE,
 };
 
 } // namespace Property
index 81b82d8..7b5e36e 100644 (file)
@@ -31,6 +31,7 @@
 #include <dali-toolkit/internal/text/bidirectional-support.h>
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/color-segmentation.h>
+#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
 #include <dali-toolkit/internal/text/markup-processor.h>
@@ -40,7 +41,6 @@
 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
 #include <dali-toolkit/internal/text/text-font-style.h>
 #include <dali-toolkit/internal/text/text-model.h>
-#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
 
 namespace Dali
 {
@@ -835,7 +835,7 @@ void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRen
     {
       Length finalNumberOfGlyphs = 0u;
 
-      if((GetLineHeight(line)) > textLayoutArea.height)
+      if((GetLineHeight(line, (lines.Size() == 1))) > textLayoutArea.height)
       {
         // The height of the line is bigger than the height of the text area.
         // Show the ellipsis glyph even if it doesn't fit in the text area.
@@ -1528,12 +1528,14 @@ Dali::Property::Array RenderForLastIndex(RendererParameters& textParameters)
   float            penY               = 0.f;
   float            lineSize           = internalData.layoutEngine.GetDefaultLineSize();
   float            lineOffset         = 0.f;
+  bool             isLastLine;
   for(unsigned int index = 0u; index < numberOfLines; ++index)
   {
     const LineRun& line = *(lines.Begin() + index);
     numberOfCharacters += line.characterRun.numberOfCharacters;
+    isLastLine = (index == numberOfLines - 1);
 
-    lineOffset = lineSize > 0.f ? lineSize : GetLineHeight(line);
+    lineOffset = lineSize > 0.f ? lineSize : GetLineHeight(line, isLastLine);
     penY += lineOffset;
     if((penY + lineOffset) > boundingBox)
     {
index bfe280a..3d71f4d 100644 (file)
@@ -1286,45 +1286,30 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         std::string name;
         if(value.Get(name))
         {
-          controlImpl.mImpl->mAccessibilityName    = name;
-          controlImpl.mImpl->mAccessibilityNameSet = true;
-        }
-        else
-        {
-          controlImpl.mImpl->mAccessibilityNameSet = false;
+          controlImpl.mImpl->mAccessibilityName = name;
         }
+        break;
       }
-      break;
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
       {
         std::string text;
         if(value.Get(text))
         {
-          controlImpl.mImpl->mAccessibilityDescription    = text;
-          controlImpl.mImpl->mAccessibilityDescriptionSet = true;
-        }
-        else
-        {
-          controlImpl.mImpl->mAccessibilityDescriptionSet = false;
+          controlImpl.mImpl->mAccessibilityDescription = text;
         }
+        break;
       }
-      break;
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
       {
         std::string text;
         if(value.Get(text))
         {
-          controlImpl.mImpl->mAccessibilityTranslationDomain    = text;
-          controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
-        }
-        else
-        {
-          controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
+          controlImpl.mImpl->mAccessibilityTranslationDomain = text;
         }
+        break;
       }
-      break;
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
       {
@@ -1333,23 +1318,18 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         {
           controlImpl.mImpl->mAccessibilityRole = role;
         }
+        break;
       }
-      break;
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
       {
         bool highlightable;
         if(value.Get(highlightable))
         {
-          controlImpl.mImpl->mAccessibilityHighlightable    = highlightable;
-          controlImpl.mImpl->mAccessibilityHighlightableSet = true;
-        }
-        else
-        {
-          controlImpl.mImpl->mAccessibilityHighlightableSet = false;
+          controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
         }
+        break;
       }
-      break;
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
       {
@@ -1502,28 +1482,19 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
       {
-        if(controlImpl.mImpl->mAccessibilityNameSet)
-        {
-          value = controlImpl.mImpl->mAccessibilityName;
-        }
+        value = controlImpl.mImpl->mAccessibilityName;
         break;
       }
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
       {
-        if(controlImpl.mImpl->mAccessibilityDescriptionSet)
-        {
-          value = controlImpl.mImpl->mAccessibilityDescription;
-        }
+        value = controlImpl.mImpl->mAccessibilityDescription;
         break;
       }
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
       {
-        if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
-        {
-          value = controlImpl.mImpl->mAccessibilityTranslationDomain;
-        }
+        value = controlImpl.mImpl->mAccessibilityTranslationDomain;
         break;
       }
 
@@ -1535,10 +1506,7 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
       {
-        if(controlImpl.mImpl->mAccessibilityHighlightableSet)
-        {
-          value = controlImpl.mImpl->mAccessibilityHighlightable;
-        }
+        value = controlImpl.mImpl->mAccessibilityHighlightable;
         break;
       }
 
index a227648..1321a10 100644 (file)
@@ -539,14 +539,9 @@ public:
   std::string mAccessibilityName;
   std::string mAccessibilityDescription;
   std::string mAccessibilityTranslationDomain;
-  bool        mAccessibilityNameSet              = false;
-  bool        mAccessibilityDescriptionSet       = false;
-  bool        mAccessibilityTranslationDomainSet = false;
 
-  bool mAccessibilityHighlightable    = false;
-  bool mAccessibilityHighlightableSet = false;
-
-  bool mAccessibilityHidden = false;
+  bool mAccessibilityHighlightable = false;
+  bool mAccessibilityHidden        = false;
 
   Dali::Accessibility::Role mAccessibilityRole = Dali::Accessibility::Role::UNKNOWN;
 
index 40fdcad..6fc1a3d 100644 (file)
@@ -158,6 +158,7 @@ DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "minLineSize",
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "strikethrough",                        MAP,       STRIKETHROUGH                       )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "inputStrikethrough",                   MAP,       INPUT_STRIKETHROUGH                 )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "characterSpacing",                     FLOAT,     CHARACTER_SPACING                   )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "relativeLineSize",                     FLOAT,     RELATIVE_LINE_SIZE                  )
 
 DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "textChanged",           SIGNAL_TEXT_CHANGED           )
 DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "inputStyleChanged",     SIGNAL_INPUT_STYLE_CHANGED    )
index 3cb9df0..5ea2cf1 100644 (file)
@@ -723,6 +723,15 @@ void TextEditor::PropertyHandler::SetProperty(Toolkit::TextEditor textEditor, Pr
       impl.mRenderer.Reset();
       break;
     }
+    case Toolkit::DevelTextEditor::Property::RELATIVE_LINE_SIZE:
+    {
+      const float relativeLineSize = value.Get<float>();
+      DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor %p RELATIVE_LINE_SIZE %f\n", impl.mController.Get(), relativeLineSize);
+
+      impl.mController->SetRelativeLineSize(relativeLineSize);
+      impl.mRenderer.Reset();
+      break;
+    }
   }
 }
 
@@ -1130,6 +1139,11 @@ Property::Value TextEditor::PropertyHandler::GetProperty(Toolkit::TextEditor tex
       value = impl.mController->GetCharacterSpacing();
       break;
     }
+    case Toolkit::DevelTextEditor::Property::RELATIVE_LINE_SIZE:
+    {
+      value = impl.mController->GetRelativeLineSize();
+      break;
+    }
   } //switch
   return value;
 }
index 49a9af8..10b05a0 100644 (file)
@@ -140,6 +140,7 @@ DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "enableFontSizeSc
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "ellipsisPosition",             INTEGER, ELLIPSIS_POSITION              )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "strikethrough",                MAP,     STRIKETHROUGH                  )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "characterSpacing",             FLOAT,   CHARACTER_SPACING              )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "relativeLineSize",             FLOAT,   RELATIVE_LINE_SIZE             )
 
 DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT(Toolkit, TextLabel, "textColor",      Color::BLACK,     TEXT_COLOR   )
 DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION(Toolkit,    TextLabel, "textColorRed",   TEXT_COLOR_RED,   TEXT_COLOR, 0)
@@ -541,6 +542,14 @@ void TextLabel::SetProperty(BaseObject* object, Property::Index index, const Pro
         impl.mController->SetCharacterSpacing(characterSpacing);
         break;
       }
+      case Toolkit::DevelTextLabel::Property::RELATIVE_LINE_SIZE:
+      {
+        const float relativeLineSize = value.Get<float>();
+        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextLabel %p RELATIVE_LINE_SIZE %f\n", impl.mController.Get(), relativeLineSize);
+
+        impl.mController->SetRelativeLineSize(relativeLineSize);
+        break;
+      }
     }
 
     // Request relayout when text update is needed. It's necessary to call it
@@ -799,6 +808,11 @@ Property::Value TextLabel::GetProperty(BaseObject* object, Property::Index index
         value = impl.mController->GetCharacterSpacing();
         break;
       }
+      case Toolkit::DevelTextLabel::Property::RELATIVE_LINE_SIZE:
+      {
+        value = impl.mController->GetRelativeLineSize();
+        break;
+      }
     }
   }
 
index 9137a2f..3bfc059 100644 (file)
@@ -153,9 +153,10 @@ LineIndex GetClosestLine(VisualModelPtr visualModel,
       it != endIt;
       ++it, ++lineIndex)
   {
-    const LineRun& lineRun = *it;
+    const LineRun& lineRun    = *it;
+    bool           isLastLine = (it + 1 == endIt);
 
-    totalHeight += GetLineHeight(lineRun);
+    totalHeight += GetLineHeight(lineRun, isLastLine);
 
     if(visualY < totalHeight)
     {
@@ -182,9 +183,10 @@ float CalculateLineOffset(const Vector<LineRun>& lines,
       it != endIt;
       ++it)
   {
-    const LineRun& lineRun = *it;
+    const LineRun& lineRun    = *it;
+    bool           isLastLine = (it + 1 == lines.End());
 
-    offset += GetLineHeight(lineRun);
+    offset += GetLineHeight(lineRun, isLastLine);
   }
 
   return offset;
index c8addcc..53030e2 100644 (file)
@@ -37,11 +37,18 @@ namespace Toolkit
 {
 namespace Text
 {
-float GetLineHeight(const LineRun lineRun)
+float GetLineHeight(const LineRun lineRun, bool isLastLine)
 {
   // The line height is the addition of the line ascender, the line descender and the line spacing.
   // However, the line descender has a negative value, hence the subtraction.
-  return lineRun.ascender - lineRun.descender + lineRun.lineSpacing;
+  // In case this is the only/last line then line spacing should be ignored.
+  float lineHeight = lineRun.ascender - lineRun.descender;
+
+  if(!isLastLine || lineRun.lineSpacing > 0)
+  {
+    lineHeight += lineRun.lineSpacing;
+  }
+  return lineHeight;
 }
 
 namespace Layout
@@ -52,12 +59,13 @@ namespace
 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_LAYOUT");
 #endif
 
-const float              MAX_FLOAT      = std::numeric_limits<float>::max();
-const CharacterDirection LTR            = false;
-const CharacterDirection RTL            = !LTR;
-const float              LINE_SPACING   = 0.f;
-const float              MIN_LINE_SIZE  = 0.f;
-const Character          HYPHEN_UNICODE = 0x002D;
+const float              MAX_FLOAT          = std::numeric_limits<float>::max();
+const CharacterDirection LTR                = false;
+const CharacterDirection RTL                = !LTR;
+const float              LINE_SPACING       = 0.f;
+const float              MIN_LINE_SIZE      = 0.f;
+const Character          HYPHEN_UNICODE     = 0x002D;
+const float              RELATIVE_LINE_SIZE = 1.f;
 
 inline bool isEmptyLineAtLast(const Vector<LineRun>& lines, const Vector<LineRun>::Iterator& line)
 {
@@ -155,8 +163,52 @@ struct Engine::Impl
   : mLayout{Layout::Engine::SINGLE_LINE_BOX},
     mCursorWidth{0.f},
     mDefaultLineSpacing{LINE_SPACING},
-    mDefaultLineSize{MIN_LINE_SIZE}
+    mDefaultLineSize{MIN_LINE_SIZE},
+    mRelativeLineSize{RELATIVE_LINE_SIZE}
+  {
+  }
+
+  /**
+   * @brief get the line spacing.
+   *
+   * @param[in] textSize The text size.
+   * @return the line spacing value.
+   */
+  float GetLineSpacing(float textSize)
   {
+    float lineSpacing;
+    float relTextSize;
+
+    // Sets the line size
+    lineSpacing = mDefaultLineSize - textSize;
+    lineSpacing = lineSpacing < 0.f ? 0.f : lineSpacing;
+
+    // Add the line spacing
+    lineSpacing += mDefaultLineSpacing;
+
+    //subtract line spcaing if relativeLineSize < 1 & larger than min height
+    relTextSize = textSize * mRelativeLineSize;
+    if(relTextSize > mDefaultLineSize)
+    {
+      if(mRelativeLineSize < 1)
+      {
+        //subtract the difference (always will be positive)
+        lineSpacing -= (textSize - relTextSize);
+      }
+      else
+      {
+        //reverse the addition in the top.
+        if(mDefaultLineSize > textSize)
+        {
+          lineSpacing -= mDefaultLineSize - textSize;
+        }
+
+        //add difference instead
+        lineSpacing += relTextSize - textSize;
+      }
+    }
+
+    return lineSpacing;
   }
 
   /**
@@ -187,12 +239,7 @@ struct Engine::Impl
     // Sets the minimum descender.
     lineLayout.descender = std::min(lineLayout.descender, fontMetrics.descender);
 
-    // Sets the line size
-    lineLayout.lineSpacing = mDefaultLineSize - (lineLayout.ascender + -lineLayout.descender);
-    lineLayout.lineSpacing = lineLayout.lineSpacing < 0.f ? 0.f : lineLayout.lineSpacing;
-
-    // Add the line spacing
-    lineLayout.lineSpacing += mDefaultLineSpacing;
+    lineLayout.lineSpacing = GetLineSpacing(lineLayout.ascender + -lineLayout.descender);
   }
 
   /**
@@ -1257,7 +1304,7 @@ struct Engine::Impl
       layoutSize.width = layoutParameters.boundingBox.width;
       if(layoutSize.height < Math::MACHINE_EPSILON_1000)
       {
-        layoutSize.height += GetLineHeight(*lineRun);
+        layoutSize.height += GetLineHeight(*lineRun, true);
       }
 
       const Vector<BidirectionalLineInfoRun>& bidirectionalLinesInfo = layoutParameters.textModel->mLogicalModel->mBidirectionalLineInfo;
@@ -1353,10 +1400,7 @@ struct Engine::Impl
     lineRun.direction = layout.direction;
     lineRun.ellipsis  = false;
 
-    lineRun.lineSpacing = mDefaultLineSize - (lineRun.ascender + -lineRun.descender);
-    lineRun.lineSpacing = lineRun.lineSpacing < 0.f ? 0.f : lineRun.lineSpacing;
-
-    lineRun.lineSpacing += mDefaultLineSpacing;
+    lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender);
 
     // Update the actual size.
     if(lineRun.width > layoutSize.width)
@@ -1364,7 +1408,7 @@ struct Engine::Impl
       layoutSize.width = lineRun.width;
     }
 
-    layoutSize.height += GetLineHeight(lineRun);
+    layoutSize.height += GetLineHeight(lineRun, isLastLine);
   }
 
   /**
@@ -1410,12 +1454,9 @@ struct Engine::Impl
     lineRun.direction                       = LTR;
     lineRun.ellipsis                        = false;
 
-    lineRun.lineSpacing = mDefaultLineSize - (lineRun.ascender + -lineRun.descender);
-    lineRun.lineSpacing = lineRun.lineSpacing < 0.f ? 0.f : lineRun.lineSpacing;
+    lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender);
 
-    lineRun.lineSpacing += mDefaultLineSpacing;
-
-    layoutSize.height += GetLineHeight(lineRun);
+    layoutSize.height += GetLineHeight(lineRun, true);
   }
 
   /**
@@ -1432,14 +1473,15 @@ struct Engine::Impl
         it != endIt;
         ++it)
     {
-      const LineRun& line = *it;
+      const LineRun& line       = *it;
+      bool           isLastLine = (it + 1 == endIt);
 
       if(line.width > layoutSize.width)
       {
         layoutSize.width = line.width;
       }
 
-      layoutSize.height += GetLineHeight(line);
+      layoutSize.height += GetLineHeight(line, isLastLine);
     }
   }
 
@@ -1811,14 +1853,7 @@ struct Engine::Impl
         }
 
         // Updates the vertical pen's position.
-        penY += -layout.descender + layout.lineSpacing + mDefaultLineSpacing;
-        // If there is a defaultLineSize, updates the pen's position.
-        if(mDefaultLineSize > 0.f)
-        {
-          float lineSpacing = mDefaultLineSize - (layout.ascender + -layout.descender);
-          lineSpacing       = lineSpacing < 0.f ? 0.f : lineSpacing;
-          penY += lineSpacing;
-        }
+        penY += -layout.descender + layout.lineSpacing + GetLineSpacing(layout.ascender + -layout.descender);
 
         // Increase the glyph index.
         index = nextIndex;
@@ -2077,6 +2112,7 @@ struct Engine::Impl
   float mDefaultLineSize;
 
   IntrusivePtr<Metrics> mMetrics;
+  float                 mRelativeLineSize;
 };
 
 Engine::Engine()
@@ -2168,6 +2204,16 @@ float Engine::GetDefaultLineSize() const
   return mImpl->mDefaultLineSize;
 }
 
+void Engine::SetRelativeLineSize(float relativeLineSize)
+{
+  mImpl->mRelativeLineSize = relativeLineSize;
+}
+
+float Engine::GetRelativeLineSize() const
+{
+  return mImpl->mRelativeLineSize;
+}
+
 } // namespace Layout
 
 } // namespace Text
index e11c549..6b78e87 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_TEXT_LAYOUT_ENGINE_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -166,6 +166,20 @@ public:
    */
   float GetDefaultLineSize() const;
 
+  /**
+   * @brief Sets relative line size to the original line size.
+   *
+   * @param[in] relativeLineSize The relative line size.
+   */
+  void SetRelativeLineSize(float relativeLineSize);
+
+  /**
+   * @brief Retrieves the relative line size.
+   *
+   * @return The relative line size.
+   */
+  float GetRelativeLineSize() const;
+
 private:
   // Undefined
   Engine(const Engine& handle);
index 52c47a1..c0bb095 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_TEXT_LINE_RUN_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -52,8 +52,9 @@ struct LineRun
  * @brief Get the line height for the specified line run.
  *
  * @param[in] lineRun The line runs to get the height for.
+ * @param[in] isLastLine whether this is the last line in the text.
  */
-float GetLineHeight(const LineRun lineRun);
+float GetLineHeight(const LineRun lineRun, bool isLastLine);
 
 } // namespace Text
 
index 40a508d..d7bf5eb 100644 (file)
@@ -26,6 +26,7 @@
 #include <dali-toolkit/internal/text/font-description-run.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-underline.h>
 
 namespace Dali
 {
@@ -42,9 +43,22 @@ const std::string XHTML_WIDTH_ATTRIBUTE("font-width");
 const std::string XHTML_SLANT_ATTRIBUTE("font-slant");
 
 const std::string XHTML_COLOR_ATTRIBUTE("text-color");
+
+//the underlined character's attributes
+const std::string XHTML_UNDERLINE_COLOR_ATTRIBUTE("u-color");
+const std::string XHTML_UNDERLINE_HEIGHT_ATTRIBUTE("u-height");
+const std::string XHTML_UNDERLINE_TYPE_ATTRIBUTE("u-type");
+const std::string XHTML_UNDERLINE_DASH_GAP_ATTRIBUTE("u-dash-gap");
+const std::string XHTML_UNDERLINE_DASH_WIDTH_ATTRIBUTE("u-dash-width");
 } // namespace
 
-void ProcessSpanTag(const Tag& tag, ColorRun& colorRun, FontDescriptionRun& fontRun, bool& isColorDefined, bool& isFontDefined)
+void ProcessSpanTag(const Tag&              tag,
+                    ColorRun&               colorRun,
+                    FontDescriptionRun&     fontRun,
+                    UnderlinedCharacterRun& underlinedCharacterRun,
+                    bool&                   isColorDefined,
+                    bool&                   isFontDefined,
+                    bool&                   isUnderlinedCharacterDefined)
 {
   for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
                                        endIt = tag.attributes.End();
@@ -83,6 +97,31 @@ void ProcessSpanTag(const Tag& tag, ColorRun& colorRun, FontDescriptionRun& font
       isFontDefined = true;
       ProcessFontSlant(attribute, fontRun);
     }
+    else if(TokenComparison(XHTML_UNDERLINE_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isUnderlinedCharacterDefined = true;
+      ProcessColorAttribute(attribute, underlinedCharacterRun);
+    }
+    else if(TokenComparison(XHTML_UNDERLINE_HEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isUnderlinedCharacterDefined = true;
+      ProcessHeightAttribute(attribute, underlinedCharacterRun);
+    }
+    else if(TokenComparison(XHTML_UNDERLINE_TYPE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isUnderlinedCharacterDefined = true;
+      ProcessTypeAttribute(attribute, underlinedCharacterRun);
+    }
+    else if(TokenComparison(XHTML_UNDERLINE_DASH_GAP_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isUnderlinedCharacterDefined = true;
+      ProcessDashGapAttribute(attribute, underlinedCharacterRun);
+    }
+    else if(TokenComparison(XHTML_UNDERLINE_DASH_WIDTH_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isUnderlinedCharacterDefined = true;
+      ProcessDashWidthAttribute(attribute, underlinedCharacterRun);
+    }
   }
 }
 
index 330caf1..f5c49f6 100644 (file)
@@ -33,10 +33,18 @@ struct MarkupProcessData;
  * @param[in] tag The span tag and its attributes.
  * @param[out] colorRun the color run to be filled.
  * @param[out] fontRun the font run to be filled.
+ * @param[out] underlinedCharacterRun the underlined character 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.
  */
-void ProcessSpanTag(const Tag& tag, ColorRun& colorRun, FontDescriptionRun& fontRun, bool& isColorDefined, bool& isFontDefined);
+void ProcessSpanTag(const Tag&              tag,
+                    ColorRun&               colorRun,
+                    FontDescriptionRun&     fontRun,
+                    UnderlinedCharacterRun& underlinedCharacterRun,
+                    bool&                   isColorDefined,
+                    bool&                   isFontDefined,
+                    bool&                   isUnderlinedCharacterDefined);
 
 } // namespace Text
 
index 063f3fe..8f19b5a 100644 (file)
@@ -108,6 +108,44 @@ void ProcessUnderlineTag(const Tag& tag, UnderlinedCharacterRun& underlinedChara
   }
 }
 
+void OverrideNestedUnderlinedCharacterRuns(Vector<UnderlinedCharacterRun>& underlinedCharacterRuns)
+{
+  // Handle nested tags
+  // The inner tag inherit the attributes of the outer tag and override them when defined in the inner tag.
+  // Example:
+  // <u height='5.0f' color='blue'> outer tag before  <u color='green'> inner tag </u> outer tag after </u>
+  // "outer tag before" and  "outer tag after" have height = 5.0f and color = 'blue'
+  // "inner tag" has height = 5.0f and color = 'green'
+
+  if(underlinedCharacterRuns.Count() > 0u)
+  {
+    Vector<UnderlinedCharacterRun>::ConstIterator preIt = underlinedCharacterRuns.Begin();
+
+    Vector<UnderlinedCharacterRun>::Iterator      it    = underlinedCharacterRuns.Begin() + 1;
+    Vector<UnderlinedCharacterRun>::ConstIterator endIt = underlinedCharacterRuns.End();
+
+    while(it != endIt)
+    {
+      const UnderlinedCharacterRun& run                = *it;
+      const CharacterIndex&         characterIndex     = run.characterRun.characterIndex;
+      const Length&                 numberOfCharacters = run.characterRun.numberOfCharacters;
+
+      const UnderlinedCharacterRun& preRun                = *preIt;
+      const CharacterIndex&         preCharacterIndex     = preRun.characterRun.characterIndex;
+      const Length&                 preNumberOfCharacters = preRun.characterRun.numberOfCharacters;
+
+      if((preCharacterIndex <= characterIndex) &&
+         ((characterIndex + numberOfCharacters) <= (preCharacterIndex + preNumberOfCharacters)))
+      {
+        it->properties.CopyIfNotDefined(preIt->properties);
+      }
+
+      it++;
+      preIt++;
+    }
+  }
+}
+
 } // namespace Text
 
 } // namespace Toolkit
index f210718..cde347c 100644 (file)
  *
  */
 
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/underlined-character-run.h>
+
 namespace Dali
 {
 namespace Toolkit
@@ -26,7 +32,6 @@ namespace Text
 {
 struct Tag;
 struct Attribute;
-struct UnderlinedCharacterRun;
 
 /**
  * @brief Fill the underlined character run with the type attribute value.
@@ -76,6 +81,13 @@ void ProcessColorAttribute(const Attribute& attribute, UnderlinedCharacterRun& u
  */
 void ProcessUnderlineTag(const Tag& tag, UnderlinedCharacterRun& underlinedCharacterRun);
 
+/**
+ * @brief Override the run's attributes which contained in the previous run. This is to handle the nested tags.
+ *
+ * @param[in,out] underlinedCharacterRuns The list of underlined character run
+ */
+void OverrideNestedUnderlinedCharacterRuns(Vector<UnderlinedCharacterRun>& underlinedCharacterRuns);
+
 } // namespace Text
 
 } // namespace Toolkit
index b41d70b..197dff1 100644 (file)
@@ -83,7 +83,7 @@ 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 = 5u;  ///< The font tag has the 'family', 'size' 'weight', 'width' and 'slant' attrubutes.
+const unsigned int MAX_NUM_OF_ATTRIBUTES = 11u; ///< 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'and 'u-dash-width' attrubutes.
 const unsigned int DEFAULT_VECTOR_SIZE   = 16u; ///< Default size of run vectors.
 
 #if defined(DEBUG_ENABLED)
@@ -140,8 +140,10 @@ struct Span
 {
   RunIndex colorRunIndex;
   RunIndex fontRunIndex;
+  RunIndex underlinedCharacterRunIndex;
   bool     isColorDefined;
   bool     isFontDefined;
+  bool     isUnderlinedCharacterDefined;
 };
 
 /**
@@ -195,10 +197,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;
 }
 
 /**
@@ -719,14 +723,16 @@ 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,
-  RunIndex&                   colorRunIndex,
-  RunIndex&                   fontRunIndex,
-  const CharacterIndex        characterIndex,
-  int&                        tagReference)
+  const Tag&                      spanTag,
+  StyleStack<Span>&               spanStack,
+  Vector<ColorRun>&               colorRuns,
+  Vector<FontDescriptionRun>&     fontRuns,
+  Vector<UnderlinedCharacterRun>& underlinedCharacterRuns,
+  RunIndex&                       colorRunIndex,
+  RunIndex&                       fontRunIndex,
+  RunIndex&                       underlinedCharacterRunIndex,
+  const CharacterIndex            characterIndex,
+  int&                            tagReference)
 {
   if(!spanTag.isEndTag)
   {
@@ -737,17 +743,22 @@ void ProcessSpanForRun(
     FontDescriptionRun fontRun;
     Initialize(fontRun);
 
+    UnderlinedCharacterRun underlinedCharacterRun;
+    Initialize(underlinedCharacterRun);
+
     Span span;
     Initialize(span);
 
     // Fill the run with the parameters.
-    colorRun.characterRun.characterIndex = characterIndex;
-    fontRun.characterRun.characterIndex  = characterIndex;
+    colorRun.characterRun.characterIndex               = characterIndex;
+    fontRun.characterRun.characterIndex                = characterIndex;
+    underlinedCharacterRun.characterRun.characterIndex = characterIndex;
 
-    span.colorRunIndex = colorRunIndex;
-    span.fontRunIndex  = fontRunIndex;
+    span.colorRunIndex               = colorRunIndex;
+    span.fontRunIndex                = fontRunIndex;
+    span.underlinedCharacterRunIndex = underlinedCharacterRunIndex;
 
-    ProcessSpanTag(spanTag, colorRun, fontRun, span.isColorDefined, span.isFontDefined);
+    ProcessSpanTag(spanTag, colorRun, fontRun, underlinedCharacterRun, span.isColorDefined, span.isFontDefined, span.isUnderlinedCharacterDefined);
 
     // Push the span into the stack.
     spanStack.Push(span);
@@ -767,6 +778,13 @@ void ProcessSpanForRun(
       ++fontRunIndex;
     }
 
+    if(span.isUnderlinedCharacterDefined)
+    {
+      // Push the run in the logical model.
+      underlinedCharacterRuns.PushBack(underlinedCharacterRun);
+      ++underlinedCharacterRunIndex;
+    }
+
     // Increase reference
     ++tagReference;
   }
@@ -789,6 +807,12 @@ void ProcessSpanForRun(
         fontRun.characterRun.numberOfCharacters = characterIndex - fontRun.characterRun.characterIndex;
       }
 
+      if(span.isUnderlinedCharacterDefined)
+      {
+        UnderlinedCharacterRun& underlinedCharacterRun         = *(underlinedCharacterRuns.Begin() + span.underlinedCharacterRunIndex);
+        underlinedCharacterRun.characterRun.numberOfCharacters = characterIndex - underlinedCharacterRun.characterRun.characterIndex;
+      }
+
       --tagReference;
     }
   }
@@ -1017,7 +1041,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
         /* Underline */
         ProcessTagForRun<UnderlinedCharacterRun>(
           markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) {
-            run.properties.color = Color::BLUE;
+            run.properties.color        = Color::BLUE;
             run.properties.colorDefined = true;
             ProcessUnderlineTag(tag, run);
           });
@@ -1048,7 +1072,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
       }
       else if(TokenComparison(XHTML_SPAN_TAG, tag.buffer, tag.length))
       {
-        ProcessSpanForRun(tag, spanStack, markupProcessData.colorRuns, markupProcessData.fontRuns, colorRunIndex, fontRunIndex, characterIndex, spanTagReference);
+        ProcessSpanForRun(tag, spanStack, markupProcessData.colorRuns, markupProcessData.fontRuns, markupProcessData.underlinedCharacterRuns, colorRunIndex, fontRunIndex, underlinedCharacterRunIndex, characterIndex, spanTagReference);
       }
       else if(TokenComparison(XHTML_STRIKETHROUGH_TAG, tag.buffer, tag.length))
       {
@@ -1070,6 +1094,9 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
 
   // Resize the model's vectors.
   ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, backgroundRunIndex, boundedParagraphRunIndex);
+
+  // Handle the nested tags
+  OverrideNestedUnderlinedCharacterRuns(markupProcessData.underlinedCharacterRuns);
 }
 
 } // namespace Text
index 9eb2fd6..291c187 100644 (file)
@@ -564,8 +564,8 @@ struct AtlasRenderer::Impl
 
       Vector<UnderlinedGlyphRun>::ConstIterator currentUnderlinedGlyphRunIt = underlineRuns.End();
       const bool                                isGlyphUnderlined           = underlineEnabled || IsGlyphUnderlined(i, underlineRuns, currentUnderlinedGlyphRunIt);
-      const UnderlineStyleProperties            currentUnderlineProperties  = GetCurrentUnderlineProperties(isGlyphUnderlined, underlineRuns, currentUnderlinedGlyphRunIt, viewUnderlineProperties);
-      float                                     currentUnderlineHeight      = GetCurrentUnderlineHeight(underlineRuns, currentUnderlinedGlyphRunIt, viewUnderlineProperties.height);
+      const UnderlineStyleProperties            currentUnderlineProperties  = GetCurrentUnderlineProperties(i, isGlyphUnderlined, underlineRuns, currentUnderlinedGlyphRunIt, viewUnderlineProperties);
+      float                                     currentUnderlineHeight      = currentUnderlineProperties.height;
       thereAreUnderlinedGlyphs                                              = thereAreUnderlinedGlyphs || isGlyphUnderlined;
 
       currentStrikethroughColor       = strikethroughColor;
@@ -655,10 +655,10 @@ struct AtlasRenderer::Impl
 
           //The new underlined chunk. Add new id if they are not consecutive indices (this is for Markup case)
           // Examples: "Hello <u>World</u> Hello <u>World</u>", "<u>World</u> Hello <u>World</u>", "<u>   World</u> Hello <u>World</u>"
-          if(isPreUnderlined && (!isGlyphUnderlined || (preUnderlineProperties != currentUnderlineProperties)))
+          if((!isPreUnderlined && isGlyphUnderlined) || (isGlyphUnderlined && (preUnderlineProperties != currentUnderlineProperties)))
           {
-            mapUnderlineChunkIdWithProperties.insert(std::pair<uint32_t, UnderlineStyleProperties>(underlineChunkId, preUnderlineProperties));
             underlineChunkId++;
+            mapUnderlineChunkIdWithProperties.insert(std::pair<uint32_t, UnderlineStyleProperties>(underlineChunkId, currentUnderlineProperties));
           }
 
           //Keep status of underlined for previous glyph to check consecutive indices
index 6720b91..873ef86 100644 (file)
@@ -45,27 +45,34 @@ bool IsGlyphUnderlined(GlyphIndex                                 index,
   return false;
 }
 
-float GetCurrentUnderlineHeight(const Vector<UnderlinedGlyphRun>&         underlineRuns,
-                                Vector<UnderlinedGlyphRun>::ConstIterator currentUnderlinedGlyphRunIt,
-                                const float                               underlineHeight)
+UnderlineStyleProperties GetCurrentUnderlineProperties(GlyphIndex                                 index,
+                                                       const bool&                                isGlyphUnderlined,
+                                                       const Vector<UnderlinedGlyphRun>&          underlineRuns,
+                                                       Vector<UnderlinedGlyphRun>::ConstIterator& currentUnderlinedGlyphRunIt,
+                                                       const UnderlineStyleProperties&            commonUnderlineProperties)
 {
-  if(currentUnderlinedGlyphRunIt == underlineRuns.End())
+  UnderlineStyleProperties currentUnderlineStyleProperties = commonUnderlineProperties;
+
+  if(isGlyphUnderlined && (currentUnderlinedGlyphRunIt != underlineRuns.End()))
   {
-    return underlineHeight;
-  }
+    // Retrieve the latest run to handle the nested case.
+    for(Vector<UnderlinedGlyphRun>::ConstIterator it    = currentUnderlinedGlyphRunIt + 1,
+                                                  endIt = underlineRuns.End();
+        it != endIt;
+        ++it)
+    {
+      const UnderlinedGlyphRun& run = *it;
 
-  const UnderlinedGlyphRun& underlinedGlyphRun = *currentUnderlinedGlyphRunIt;
-  return (underlinedGlyphRun.properties.heightDefined ? underlinedGlyphRun.properties.height : underlineHeight);
-}
+      if((run.glyphRun.glyphIndex <= index) && (index < (run.glyphRun.glyphIndex + run.glyphRun.numberOfGlyphs)))
+      {
+        currentUnderlinedGlyphRunIt = it;
+      }
+    }
 
-UnderlineStyleProperties GetCurrentUnderlineProperties(const bool&                               isGlyphUnderlined,
-                                                       const Vector<UnderlinedGlyphRun>&         underlineRuns,
-                                                       Vector<UnderlinedGlyphRun>::ConstIterator currentUnderlinedGlyphRunIt,
-                                                       const UnderlineStyleProperties&           commonUnderlineProperties)
-{
-  return (isGlyphUnderlined && (currentUnderlinedGlyphRunIt != underlineRuns.End()))
-           ? currentUnderlinedGlyphRunIt->properties
-           : commonUnderlineProperties;
+    currentUnderlineStyleProperties.OverrideByDefinedProperties(currentUnderlinedGlyphRunIt->properties);
+  }
+
+  return currentUnderlineStyleProperties;
 }
 
 float FetchUnderlinePositionFromFontMetrics(const FontMetrics& fontMetrics)
index 825b05c..38471c8 100644 (file)
@@ -46,21 +46,9 @@ bool IsGlyphUnderlined(GlyphIndex                                 index,
                        Vector<UnderlinedGlyphRun>::ConstIterator& currentUnderlinedGlyphRunIt);
 
 /**
- * @brief Check the current underlined glyph run iterator if not empty and its height is defined then return ts height. Otherwise return the common underline height.
- *
- * @param[in] underlineRuns the underline runs.
- * @param[in] currentUnderlinedGlyphRunIt the iterator of current underlined glyph run.
- * @param[in] underlineHeight the common underline height.
- *
- * @return the determined underline height
- */
-float GetCurrentUnderlineHeight(const Vector<UnderlinedGlyphRun>&         underlineRuns,
-                                Vector<UnderlinedGlyphRun>::ConstIterator currentUnderlinedGlyphRunIt,
-                                const float                               underlineHeight);
-
-/**
  * @brief Check the current underlined glyph run iterator if not empty and isGlyphUnderlined is true then return its UnderlineProperties. Otherwise return the common underline properties.
  *
+ * @param[in] index the index of glyph.
  * @param[in] isGlyphUnderlined whether the glyph is underlined.
  * @param[in] underlineRuns the underline runs.
  * @param[in] currentUnderlinedGlyphRunIt the iterator of current underlined glyph run.
@@ -68,10 +56,11 @@ float GetCurrentUnderlineHeight(const Vector<UnderlinedGlyphRun>&         underl
  *
  * @return the determined underline properties
  */
-UnderlineStyleProperties GetCurrentUnderlineProperties(const bool&                               isGlyphUnderlined,
-                                                       const Vector<UnderlinedGlyphRun>&         underlineRuns,
-                                                       Vector<UnderlinedGlyphRun>::ConstIterator currentUnderlinedGlyphRunIt,
-                                                       const UnderlineStyleProperties&           commonUnderlineProperties);
+UnderlineStyleProperties GetCurrentUnderlineProperties(GlyphIndex                                 index,
+                                                       const bool&                                isGlyphUnderlined,
+                                                       const Vector<UnderlinedGlyphRun>&          underlineRuns,
+                                                       Vector<UnderlinedGlyphRun>::ConstIterator& currentUnderlinedGlyphRunIt,
+                                                       const UnderlineStyleProperties&            commonUnderlineProperties);
 
 /**
  * @brief Fetch and calculate underline Position using font-metrics
index 790e247..4dc9775 100644 (file)
@@ -1004,8 +1004,8 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth,
 
       Vector<UnderlinedGlyphRun>::ConstIterator currentUnderlinedGlyphRunIt = underlineRuns.End();
       const bool                                underlineGlyph              = underlineEnabled || IsGlyphUnderlined(glyphIndex, underlineRuns, currentUnderlinedGlyphRunIt);
-      currentUnderlineProperties                                            = GetCurrentUnderlineProperties(underlineGlyph, underlineRuns, currentUnderlinedGlyphRunIt, modelUnderlineProperties);
-      currentUnderlineHeight                                                = GetCurrentUnderlineHeight(underlineRuns, currentUnderlinedGlyphRunIt, modelUnderlineProperties.height);
+      currentUnderlineProperties                                            = GetCurrentUnderlineProperties(glyphIndex, underlineGlyph, underlineRuns, currentUnderlinedGlyphRunIt, modelUnderlineProperties);
+      currentUnderlineHeight                                                = currentUnderlineProperties.height;
       thereAreUnderlinedGlyphs                                              = thereAreUnderlinedGlyphs || underlineGlyph;
 
       currentStrikethroughColor     = strikethroughColor;
@@ -1256,24 +1256,15 @@ Devel::PixelBuffer Typesetter::ApplyUnderlineMarkupImageBuffer(Devel::PixelBuffe
   //The outer loop to iterate on the separated chunks of underlined glyph runs
   while(itGlyphRun != endItGlyphRun)
   {
-    const UnderlineStyleProperties& firstUnderlineStyleProperties = itGlyphRun->properties;
-
     startGlyphIndex = itGlyphRun->glyphRun.glyphIndex;
-    endGlyphIndex   = startGlyphIndex;
-    //The inner loop to make a connected underline for the consecutive characters
-    do
-    {
-      endGlyphIndex += itGlyphRun->glyphRun.numberOfGlyphs;
-      itGlyphRun++;
-    } while(itGlyphRun != endItGlyphRun && itGlyphRun->glyphRun.glyphIndex == endGlyphIndex &&
-            (firstUnderlineStyleProperties == itGlyphRun->properties));
-
-    endGlyphIndex--;
+    endGlyphIndex   = startGlyphIndex + itGlyphRun->glyphRun.numberOfGlyphs - 1;
 
     // Create the image buffer for underline
     Devel::PixelBuffer underlineImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_UNDERLINE, ignoreHorizontalAlignment, pixelFormat, horizontalOffset, verticalOffset, startGlyphIndex, endGlyphIndex);
     // Combine the two buffers
-    topPixelBuffer = CombineImageBuffer(topPixelBuffer, underlineImageBuffer, bufferWidth, bufferHeight);
+    topPixelBuffer = CombineImageBuffer(underlineImageBuffer, topPixelBuffer, bufferWidth, bufferHeight);
+
+    itGlyphRun++;
   }
 
   return topPixelBuffer;
index 290c229..cee6a88 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -334,6 +334,8 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const
 
     const LineIndex lineIndex         = visualModel->GetLineOfCharacter(characterIndex);
     const LineIndex previousLineIndex = (lineIndex > 0 ? lineIndex - 1u : lineIndex);
+    const LineIndex lastLineIndex     = (visualModel->mLines.Size() > 0 ? visualModel->mLines.Size() - 1u : 0);
+    const bool      isLastLine        = (previousLineIndex == lastLineIndex);
 
     // Retrieve the cursor position info.
     CursorInfo cursorInfo;
@@ -344,7 +346,7 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const
     const LineRun& line = *(visualModel->mLines.Begin() + previousLineIndex);
 
     // Get the next hit 'y' point.
-    const float hitPointY = cursorInfo.lineOffset - 0.5f * GetLineHeight(line);
+    const float hitPointY = cursorInfo.lineOffset - 0.5f * GetLineHeight(line, isLastLine);
 
     // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
     bool matchedCharacter = false;
@@ -379,8 +381,12 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const
       // Get the line below.
       const LineRun& line = *(visualModel->mLines.Begin() + lineIndex + 1u);
 
+      // Get last line index
+      const LineIndex lastLineIndex = (visualModel->mLines.Size() > 0 ? visualModel->mLines.Size() - 1u : 0);
+      const bool      isLastLine    = (lineIndex + 1u == lastLineIndex);
+
       // Get the next hit 'y' point.
-      const float hitPointY = cursorInfo.lineOffset + cursorInfo.lineHeight + 0.5f * GetLineHeight(line);
+      const float hitPointY = cursorInfo.lineOffset + cursorInfo.lineHeight + 0.5f * GetLineHeight(line, isLastLine);
 
       // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
       bool matchedCharacter = false;
index 294b534..cf49df5 100644 (file)
@@ -712,6 +712,23 @@ bool Controller::Impl::SetDefaultLineSize(float lineSize)
   return false;
 }
 
+bool Controller::Impl::SetRelativeLineSize(float relativeLineSize)
+{
+  if(std::fabs(relativeLineSize - GetRelativeLineSize()) > Math::MACHINE_EPSILON_1000)
+  {
+    mLayoutEngine.SetRelativeLineSize(relativeLineSize);
+
+    RelayoutAllCharacters();
+    return true;
+  }
+  return false;
+}
+
+float Controller::Impl::GetRelativeLineSize()
+{
+  return mLayoutEngine.GetRelativeLineSize();
+}
+
 string Controller::Impl::GetSelectedText()
 {
   string text;
@@ -1619,26 +1636,26 @@ void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearP
   {
     CharacterIndex characterIndex     = it->characterRun.characterIndex;
     Length         numberOfCharacters = it->characterRun.numberOfCharacters;
-    for(Length index = 0u; index < numberOfCharacters; index++)
+
+    if(numberOfCharacters == 0)
+    {
+      continue;
+    }
+
+    // Create one run for all glyphs of all run's characters that has same properties
+    // This enhance performance and reduce the needed memory to store glyphs-runs
+    UnderlinedGlyphRun underlineGlyphRun;
+    underlineGlyphRun.glyphRun.glyphIndex     = charactersToGlyph[characterIndex];
+    underlineGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex];
+    //Copy properties (attributes)
+    underlineGlyphRun.properties = it->properties;
+
+    for(Length index = 1u; index < numberOfCharacters; index++)
     {
-      UnderlinedGlyphRun underlineGlyphRun;
-      underlineGlyphRun.glyphRun.glyphIndex     = charactersToGlyph[characterIndex + index];
-      underlineGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex + index];
-
-      //Copy properties (attributes)
-      underlineGlyphRun.properties.type             = it->properties.type;
-      underlineGlyphRun.properties.color            = it->properties.color;
-      underlineGlyphRun.properties.height           = it->properties.height;
-      underlineGlyphRun.properties.dashGap          = it->properties.dashGap;
-      underlineGlyphRun.properties.dashWidth        = it->properties.dashWidth;
-      underlineGlyphRun.properties.typeDefined      = it->properties.typeDefined;
-      underlineGlyphRun.properties.colorDefined     = it->properties.colorDefined;
-      underlineGlyphRun.properties.heightDefined    = it->properties.heightDefined;
-      underlineGlyphRun.properties.dashGapDefined   = it->properties.dashGapDefined;
-      underlineGlyphRun.properties.dashWidthDefined = it->properties.dashWidthDefined;
-
-      mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
+      underlineGlyphRun.glyphRun.numberOfGlyphs += glyphsPerCharacter[characterIndex + index];
     }
+
+    mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
   }
 }
 
index 4b1db94..0757bc0 100644 (file)
@@ -627,6 +627,16 @@ struct Controller::Impl
   bool SetDefaultLineSize(float lineSize);
 
   /**
+   * @copydoc Controller::SetRelativeLineSize
+   */
+  bool SetRelativeLineSize(float relativeLineSize);
+
+  /**
+   * @copydoc Controller::GetRelativeLineSize
+   */
+  float GetRelativeLineSize();
+
+  /**
    * @copydoc Text::Controller::GetPrimaryCursorPosition()
    */
   CharacterIndex GetPrimaryCursorPosition() const;
index 9ea1e60..9de7dba 100644 (file)
@@ -948,6 +948,16 @@ float Controller::GetDefaultLineSize() const
   return mImpl->mLayoutEngine.GetDefaultLineSize();
 }
 
+bool Controller::SetRelativeLineSize(float relativeLineSize)
+{
+  return mImpl->SetRelativeLineSize(relativeLineSize);
+}
+
+float Controller::GetRelativeLineSize() const
+{
+  return mImpl->GetRelativeLineSize();
+}
+
 void Controller::SetInputColor(const Vector4& color)
 {
   InputProperties::SetInputColor(*this, color);
index f461058..2a37c3b 100644 (file)
@@ -1262,6 +1262,22 @@ public: // Default style & Input style
   float GetDefaultLineSize() const;
 
   /**
+   * @brief Sets the relative line size to the original line size.
+   *
+   * @param[in] relativeLineSize The relativeline size.
+   *
+   * @return True if relativeLineSize has been updated, false otherwise
+   */
+  bool SetRelativeLineSize(float lineSize);
+
+  /**
+   * @brief Retrieves the relative line size.
+   *
+   * @return The relative line size.
+   */
+  float GetRelativeLineSize() const;
+
+  /**
    * @brief Sets the input text's color.
    *
    * @param[in] color The input text's color.
index 9fa5ad1..bde5517 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -32,13 +32,14 @@ namespace Toolkit
 {
 namespace Text
 {
-bool GetNextLine(GlyphIndex index, LineIndex& lineIndex, LineRun*& lineRun, GlyphIndex& lastGlyphOfLine, Length numberOfLines)
+bool GetNextLine(GlyphIndex index, LineIndex& lineIndex, LineRun*& lineRun, GlyphIndex& lastGlyphOfLine, Length numberOfLines, bool& isLastLine)
 {
   if(index == lastGlyphOfLine)
   {
     ++lineIndex;
     if(lineIndex < numberOfLines)
     {
+      isLastLine = (lineIndex + 1 == numberOfLines);
       ++lineRun;
       return true;
     }
@@ -47,11 +48,11 @@ bool GetNextLine(GlyphIndex index, LineIndex& lineIndex, LineRun*& lineRun, Glyp
   return false;
 }
 
-void UpdateLineInfo(const LineRun* lineRun, float& currentLineOffset, float& currentLineHeight, GlyphIndex& lastGlyphOfLine)
+void UpdateLineInfo(const LineRun* lineRun, float& currentLineOffset, float& currentLineHeight, GlyphIndex& lastGlyphOfLine, bool isLastLine)
 {
   lastGlyphOfLine   = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1u;
   currentLineOffset = currentLineOffset + currentLineHeight;
-  currentLineHeight = GetLineHeight(*lineRun);
+  currentLineHeight = GetLineHeight(*lineRun, isLastLine);
 }
 
 void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterIndex endIndex, Vector<Vector2>& sizesList, Vector<Vector2>& positionsList)
@@ -100,6 +101,7 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd
   GlyphIndex   glyphEnd       = *(charactersToGlyphBuffer + endIndex) + ((numberOfGlyphs > 0) ? numberOfGlyphs - 1u : 0u);
   LineIndex    lineIndex      = visualModel->GetLineOfCharacter(startIndex);
   Length       numberOfLines  = visualModel->GetTotalNumberOfLines();
+  bool         isLastLine     = lineIndex + 1 == numberOfLines;
 
   LineIndex firstLineIndex = lineIndex;
   Size      textInLineSize;
@@ -109,7 +111,7 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd
 
   //get the first line and its vertical offset
   float      currentLineOffset = CalculateLineOffset(visualModel->mLines, firstLineIndex);
-  float      currentLineHeight = GetLineHeight(*lineRun);
+  float      currentLineHeight = GetLineHeight(*lineRun, isLastLine);
   GlyphIndex lastGlyphOfLine   = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1;
 
   // Check if the first/last glyph is a ligature that needs be splitted like English fi or Arabic ﻻ.
@@ -148,9 +150,9 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd
             positionsList.PushBack(blockPos);
           }
 
-          if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines))
+          if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines, isLastLine))
           {
-            UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine);
+            UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine, isLastLine);
           }
           // Ignore any glyph that was removed
           continue;
@@ -165,9 +167,9 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd
         }
         else if((ellipsisPosition == DevelText::EllipsisPosition::START) && (index <= startIndexOfGlyphs))
         {
-          if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines))
+          if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines, isLastLine))
           {
-            UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine);
+            UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine, isLastLine);
           }
 
           continue;
@@ -214,9 +216,9 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd
       currentSize.y     = currentLineHeight;
 
       // if there is next line to retrieve.
-      if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines))
+      if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines, isLastLine))
       {
-        UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine);
+        UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine, isLastLine);
       }
     }
 
index ed64520..fdccbe1 100644 (file)
@@ -279,7 +279,7 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
           const LineRun& elidedLine = *ellipsisLine;
 
           if((1u == numberOfLines) &&
-             (GetLineHeight(elidedLine) > mImpl->mVisualModel->mControlSize.height))
+             (GetLineHeight(elidedLine, true) > mImpl->mVisualModel->mControlSize.height))
           {
             // Replace the first glyph with ellipsis glyph
             auto indexOfFirstGlyph = (ellipsisPosition == DevelText::EllipsisPosition::START) ? startIndexOfEllipsis : 0u;
index 14016c4..d75f22b 100644 (file)
  */
 
 // EXTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
 #include <dali/public-api/math/vector4.h>
 
 // INTERNAL INCLUDES
-
 #include <dali-toolkit/public-api/text/text-enumerations.h>
 
 namespace Dali
@@ -100,6 +100,80 @@ struct UnderlineStyleProperties
     return ((!heightDefined && !other.heightDefined) || ((heightDefined && other.heightDefined) && (height == other.height)));
   }
 
+  UnderlineStyleProperties& CopyIfNotDefined(const UnderlineStyleProperties& other)
+  {
+    //Copy only the defined properties in other and not defined in this from other to this
+    if(!typeDefined && other.typeDefined)
+    {
+      type        = other.type;
+      typeDefined = true;
+    }
+
+    if(!heightDefined && other.heightDefined)
+    {
+      height        = other.height;
+      heightDefined = true;
+    }
+
+    if(!colorDefined && other.colorDefined)
+    {
+      color        = other.color;
+      colorDefined = true;
+    }
+
+    if(!dashGapDefined && other.dashGapDefined)
+    {
+      dashGap        = other.dashGap;
+      dashGapDefined = true;
+    }
+
+    if(!dashWidthDefined && other.dashWidthDefined)
+    {
+      dashWidth        = other.dashWidth;
+      dashWidthDefined = true;
+    }
+
+    // to chain this method
+    return *this;
+  }
+
+  UnderlineStyleProperties& OverrideByDefinedProperties(const UnderlineStyleProperties& other)
+  {
+    //Copy only the defined properties in other from other to this
+    if(other.typeDefined)
+    {
+      type        = other.type;
+      typeDefined = true;
+    }
+
+    if(other.heightDefined)
+    {
+      height        = other.height;
+      heightDefined = true;
+    }
+
+    if(other.colorDefined)
+    {
+      color        = other.color;
+      colorDefined = true;
+    }
+
+    if(other.dashGapDefined)
+    {
+      dashGap        = other.dashGap;
+      dashGapDefined = true;
+    }
+
+    if(other.dashWidthDefined)
+    {
+      dashWidth        = other.dashWidth;
+      dashWidthDefined = true;
+    }
+
+    // to chain this method
+    return *this;
+  }
+
   //Attributes
   Text::Underline::Type type;      ///< The type of underline.
   Vector4               color;     ///< The color of underline.
index 288ed34..81126c3 100644 (file)
@@ -1098,6 +1098,21 @@ Dali::Property Visual::Base::GetPropertyObject(Dali::Property::Key key)
       return OnGetPropertyObject(key);
     }
   }
+  else
+  {
+    if(index == mImpl->mBorderlineWidthIndex ||
+       index == mImpl->mBorderlineColorIndex ||
+       index == mImpl->mBorderlineOffsetIndex)
+    {
+      // Borderline is animated now. we always have to use borderline feature.
+      mImpl->mAlwaysUsingBorderline = true;
+    }
+    if(index == mImpl->mCornerRadiusIndex)
+    {
+      // CornerRadius is animated now. we always have to use corner radius feature.
+      mImpl->mAlwaysUsingCornerRadius = true;
+    }
+  }
 
   return Dali::Property(mImpl->mRenderer, index);
 }