Spannable: Add UnderlineSpan 81/285381/3
authorssabah <s.sabah@samsung.com>
Wed, 7 Dec 2022 21:14:05 +0000 (00:14 +0300)
committerssabah <s.sabah@samsung.com>
Mon, 12 Dec 2022 09:19:21 +0000 (12:19 +0300)
UnderlineSpan: Span to change the underline properties (Type, Color,Height, DashGap and DashWidth) of characters

This patch should be preceded by the patch below:
https://review.tizen.org/gerrit/c/platform/core/uifw/dali-toolkit/+/285217

Change-Id: Ia557197b60031a559021b72372ef304195505537

13 files changed:
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-TextSpannable.cpp
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/utc-Dali-Text-UnderlineSpan.cpp [new file with mode: 0644]
dali-toolkit/devel-api/file.list
dali-toolkit/devel-api/text/spans/underline-span.cpp [new file with mode: 0644]
dali-toolkit/devel-api/text/spans/underline-span.h [new file with mode: 0644]
dali-toolkit/internal/file.list
dali-toolkit/internal/text/controller/text-controller-impl-model-updater.cpp
dali-toolkit/internal/text/controller/text-controller-impl.cpp
dali-toolkit/internal/text/logical-model-impl.cpp
dali-toolkit/internal/text/logical-model-impl.h
dali-toolkit/internal/text/spannable/spans/underline-span-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/text/spannable/spans/underline-span-impl.h [new file with mode: 0644]

index 1f71000..1143326 100644 (file)
@@ -25,6 +25,7 @@
 #include <dali-toolkit/devel-api/text/spannable-string.h>
 #include <dali-toolkit/devel-api/text/spans/font-span.h>
 #include <dali-toolkit/devel-api/text/spans/foreground-color-span.h>
+#include <dali-toolkit/devel-api/text/spans/underline-span.h>
 #include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
 #include <dali-toolkit/internal/controls/text-controls/text-editor-impl.h>
 #include <dali-toolkit/internal/controls/text-controls/text-field-impl.h>
@@ -76,6 +77,19 @@ Text::SpannableString CreateSpannableStringForFontSpan()
   return spannableString;
 }
 
+Text::SpannableString CreateSpannableStringForUnderlineSpan()
+{
+  Text::SpannableString spannableString = Text::SpannableString::New("Hello World");
+  DALI_TEST_CHECK(spannableString);
+
+  auto isAddedUnderlineSpan = spannableString.AttachSpan(
+    Text::UnderlineSpan::NewDashed(Color::GREEN, 5.0f, 2.0f, 3.0f),
+    Text::Range::New(5u, 7u));
+  DALI_TEST_CHECK(isAddedUnderlineSpan);
+
+  return spannableString;
+}
+
 void CheckColorIndices(const Text::ColorIndex* const colorIndicesBuffer,
                        uint32_t                      numberOfIndices,
                        std::vector<uint32_t>         indicesToCheck,
@@ -302,4 +316,50 @@ int UtcDaliTextModelIsSpannedTextPlaced(void)
   tet_result(TET_PASS);
 
   END_TEST;
+}
+
+int UtcDaliToolkitTextLabelSetSpannedText_UnderlineSpan(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextLabelSetSpannedText_UnderlineSpan ");
+
+  Dali::Toolkit::Text::UnderlineStyleProperties expectedProperties = {
+    Text::Underline::DASHED,
+    Color::GREEN,
+    5u,
+    2u,
+    3u,
+    true,
+    true,
+    true,
+    true,
+    true};
+
+  TextLabel textLabel = TextLabel::New();
+  DALI_TEST_CHECK(textLabel);
+  application.GetScene().Add(textLabel);
+
+  Text::SpannableString spannableString = CreateSpannableStringForUnderlineSpan();
+
+  Text::SetSpannedText(textLabel, spannableString);
+
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextLabel& labelImpl             = GetImpl(textLabel);
+  const Text::Length            numberOfUnderlineRuns = labelImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
+
+  DALI_TEST_EQUALS(numberOfUnderlineRuns, 1u, TEST_LOCATION);
+
+  Vector<Dali::Toolkit::Text::UnderlinedGlyphRun> underlineRuns;
+
+  underlineRuns.Resize(numberOfUnderlineRuns);
+
+  labelImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
+
+  DALI_TEST_EQUALS(underlineRuns[0].glyphRun.glyphIndex, 5u, TEST_LOCATION);
+  DALI_TEST_EQUALS(underlineRuns[0].glyphRun.numberOfGlyphs, 3u, TEST_LOCATION);
+  DALI_TEST_CHECK(underlineRuns[0].properties == expectedProperties);
+
+  END_TEST;
 }
\ No newline at end of file
index f4643e3..5914024 100755 (executable)
@@ -45,6 +45,7 @@ SET(TC_SOURCES
   utc-Dali-Text-FontSpan.cpp
   utc-Dali-Text-Range.cpp
   utc-Dali-Text-SpannableString.cpp
+  utc-Dali-Text-UnderlineSpan.cpp
   utc-Dali-TextEditor.cpp
   utc-Dali-TextField.cpp
   utc-Dali-TextGeometry.cpp
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Text-UnderlineSpan.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Text-UnderlineSpan.cpp
new file mode 100644 (file)
index 0000000..c816cce
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/devel-api/text/spans/underline-span.h>
+
+using namespace Dali;
+using namespace Toolkit;
+
+int UtcDaliToolkitTextUnderlineSpanNew(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextUnderlineSpanNew");
+
+  auto underlineSpan = Text::UnderlineSpan::New();
+  DALI_TEST_CHECK(underlineSpan);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextUnderlineSpanNewSolid(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextUnderlineSpanNewSolid");
+
+  auto underlineSpan = Text::UnderlineSpan::NewSolid(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextUnderlineSpanNewDashed(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextUnderlineSpanNewDashed");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDashed(Color::GREEN, 5.0f, 2.0f, 3.0f);
+  DALI_TEST_CHECK(underlineSpan);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextUnderlineSpanNewDouble(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextUnderlineSpanNewDouble");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDouble(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextGetType(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextGetType");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDouble(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(Text::Underline::DOUBLE, underlineSpan.GetType(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextIsTypeDefined(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextIsTypeDefined");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDouble(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(true, underlineSpan.IsTypeDefined(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextGetColor(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextGetColor");
+
+  auto underlineSpan = Text::UnderlineSpan::NewSolid(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(Color::GREEN, underlineSpan.GetColor(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextIsColorDefined(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextIsColorDefined");
+
+  auto underlineSpan = Text::UnderlineSpan::NewSolid(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(true, underlineSpan.IsColorDefined(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextGetHeight(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextGetHeight");
+
+  auto underlineSpan = Text::UnderlineSpan::NewSolid(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(5.0f, underlineSpan.GetHeight(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextIsHeightDefined(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextIsHeightDefined");
+
+  auto underlineSpan = Text::UnderlineSpan::NewSolid(Color::GREEN, 5.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(true, underlineSpan.IsHeightDefined(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextGetDashGap(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextGetDashGap");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDashed(Color::GREEN, 5.0f, 2.0f, 3.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(2.0f, underlineSpan.GetDashGap(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextIsDashGapDefined(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextIsDashGapDefined");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDashed(Color::GREEN, 5.0f, 2.0f, 3.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(true, underlineSpan.IsDashGapDefined(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextGetDashWidth(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextGetDashWidth");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDashed(Color::GREEN, 5.0f, 2.0f, 3.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(3.0f, underlineSpan.GetDashWidth(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextIsDashWidthDefined(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextIsDashWidthDefined");
+
+  auto underlineSpan = Text::UnderlineSpan::NewDashed(Color::GREEN, 5.0f, 2.0f, 3.0f);
+  DALI_TEST_CHECK(underlineSpan);
+  DALI_TEST_EQUALS(true, underlineSpan.IsDashWidthDefined(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliToolkitTextUnderlineSpanDownCast(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextUnderlineSpanDownCast");
+
+  Text::BaseSpan baseSpan = Text::UnderlineSpan::New();
+  DALI_TEST_CHECK(baseSpan);
+
+  Text::UnderlineSpan underlineSpan = Text::UnderlineSpan::DownCast(baseSpan);
+  DALI_TEST_CHECK(underlineSpan);
+
+  END_TEST;
+}
index b2ac025..54cb62e 100755 (executable)
@@ -69,6 +69,7 @@ SET( devel_api_src_files
   ${devel_api_src_dir}/text/spans/base-span.cpp
   ${devel_api_src_dir}/text/spans/foreground-color-span.cpp
   ${devel_api_src_dir}/text/spans/font-span.cpp
+  ${devel_api_src_dir}/text/spans/underline-span.cpp
   ${devel_api_src_dir}/transition-effects/cube-transition-cross-effect.cpp
   ${devel_api_src_dir}/transition-effects/cube-transition-effect.cpp
   ${devel_api_src_dir}/transition-effects/cube-transition-fold-effect.cpp
@@ -251,6 +252,7 @@ SET( devel_api_text_header_files
   ${devel_api_src_dir}/text/spans/base-span.h
   ${devel_api_src_dir}/text/spans/foreground-color-span.h
   ${devel_api_src_dir}/text/spans/font-span.h
+  ${devel_api_src_dir}/text/spans/underline-span.h
 )
 
 SET( devel_api_tool_bar_header_files
diff --git a/dali-toolkit/devel-api/text/spans/underline-span.cpp b/dali-toolkit/devel-api/text/spans/underline-span.cpp
new file mode 100644 (file)
index 0000000..4760ed1
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/devel-api/text/spans/underline-span.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/spannable/spans/underline-span-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+UnderlineSpan UnderlineSpan::New()
+{
+  return Internal::UnderlineSpan::New();
+}
+
+UnderlineSpan UnderlineSpan::NewSolid(Vector4 color, float height)
+{
+  return Internal::UnderlineSpan::NewSolid(color, height);
+}
+
+UnderlineSpan UnderlineSpan::NewDashed(Vector4 color, float height, float dashGap, float dashWidth)
+{
+  return Internal::UnderlineSpan::NewDashed(color, height, dashGap, dashWidth);
+}
+
+UnderlineSpan UnderlineSpan::NewDouble(Vector4 color, float height)
+{
+  return Internal::UnderlineSpan::NewDouble(color, height);
+}
+
+UnderlineSpan::UnderlineSpan(Internal::UnderlineSpan* internal)
+: BaseSpan(internal)
+{
+}
+
+UnderlineSpan::UnderlineSpan() = default;
+
+UnderlineSpan::UnderlineSpan(const UnderlineSpan& rhs) = default;
+
+UnderlineSpan::UnderlineSpan(UnderlineSpan&& rhs) = default;
+
+UnderlineSpan& UnderlineSpan::operator=(const UnderlineSpan& rhs) = default;
+
+UnderlineSpan& UnderlineSpan::operator=(UnderlineSpan&& rhs) = default;
+
+UnderlineSpan::~UnderlineSpan() = default;
+
+//Methods
+
+const Text::Underline::Type UnderlineSpan::GetType() const
+{
+  return GetImplementation(*this).GetType();
+}
+
+bool UnderlineSpan::IsTypeDefined() const
+{
+  return GetImplementation(*this).IsTypeDefined();
+}
+
+const Vector4 UnderlineSpan::GetColor() const
+{
+  return GetImplementation(*this).GetColor();
+}
+
+bool UnderlineSpan::IsColorDefined() const
+{
+  return GetImplementation(*this).IsColorDefined();
+}
+
+const float UnderlineSpan::GetHeight() const
+{
+  return GetImplementation(*this).GetHeight();
+}
+
+bool UnderlineSpan::IsHeightDefined() const
+{
+  return GetImplementation(*this).IsHeightDefined();
+}
+
+const float UnderlineSpan::GetDashGap() const
+{
+  return GetImplementation(*this).GetDashGap();
+}
+
+bool UnderlineSpan::IsDashGapDefined() const
+{
+  return GetImplementation(*this).IsDashGapDefined();
+}
+
+const float UnderlineSpan::GetDashWidth() const
+{
+  return GetImplementation(*this).GetDashWidth();
+}
+
+bool UnderlineSpan::IsDashWidthDefined() const
+{
+  return GetImplementation(*this).IsDashWidthDefined();
+}
+
+UnderlineSpan UnderlineSpan::DownCast(BaseHandle handle)
+{
+  return UnderlineSpan(dynamic_cast<Dali::Toolkit::Text::Internal::UnderlineSpan*>(handle.GetObjectPtr()));
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/text/spans/underline-span.h b/dali-toolkit/devel-api/text/spans/underline-span.h
new file mode 100644 (file)
index 0000000..d233c73
--- /dev/null
@@ -0,0 +1,218 @@
+#ifndef DALI_TOOLKIT_TEXT_UNDERLINE_SPAN_H
+#define DALI_TOOLKIT_TEXT_UNDERLINE_SPAN_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/text/spans/base-span.h>
+#include <dali-toolkit/public-api/text/text-enumerations.h>
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/math/vector4.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace Internal DALI_INTERNAL
+{
+class UnderlineSpan;
+}
+
+/**
+ * @brief UnderlineSpan is a handle to an object that specifies the underline properties for range of characters.
+ */
+class DALI_TOOLKIT_API UnderlineSpan : public BaseSpan
+{
+public:
+  /**
+   * @brief Create an initialized UnderlineSpan.
+   *
+   * @return A handle to a newly allocated Dali resource
+   */
+  static UnderlineSpan New();
+
+  /**
+   * @brief Create an initialized UnderlineSpan.
+   *
+   * @param[in] color The color of line.
+   * @param[in] height The height of line.
+   *
+   * @return A handle to a newly allocated Dali resource
+   */
+  static UnderlineSpan NewSolid(Vector4 color, float height);
+
+  /**
+   * @brief Create an initialized UnderlineSpan.
+   *
+   * @param[in] color The color of line.
+   * @param[in] height The height of line.
+   * @param[in] dashGap The dash-gap of line.
+   * @param[in] dashWidth The dash-width of line.
+   *
+   * @return A handle to a newly allocated Dali resource
+   */
+  static UnderlineSpan NewDashed(Vector4 color, float height, float dashGap, float dashWidth);
+
+  /**
+   * @brief Create an initialized UnderlineSpan.
+   *
+   * @param[in] color The color of line.
+   * @param[in] height The height of line.
+   *
+   * @return A handle to a newly allocated Dali resource
+   */
+  static UnderlineSpan NewDouble(Vector4 color, float height);
+
+  /**
+   * @brief Creates an uninitialized UnderlineSpan handle.
+   *
+   * Calling member functions with an uninitialized UnderlineSpan handle is not allowed.
+   */
+  UnderlineSpan();
+
+  /**
+   * @brief Copy constructor.
+   * @param[in] rhs A reference to the copied handle
+   */
+  UnderlineSpan(const UnderlineSpan& rhs);
+
+  /**
+   * @brief Move constructor.
+   * @param[in] rhs A reference to the handle to move
+   */
+  UnderlineSpan(UnderlineSpan&& rhs);
+
+  /**
+   * @brief Assignment operator.
+   * @param[in] rhs A reference to the copied handle
+   * @return A reference to this
+   */
+  UnderlineSpan& operator=(const UnderlineSpan& rhs);
+
+  /**
+   * @brief Move assignment operator.
+   * @param[in] rhs A reference to the moved handle
+   * @return A reference to this
+   */
+  UnderlineSpan& operator=(UnderlineSpan&& rhs);
+
+  /**
+   * @brief Non virtual destructor.
+   */
+  ~UnderlineSpan();
+
+  /**
+   * @brief Downcasts to a UnderlineSpan handle.
+   * If handle is not a UnderlineSpan, the returned handle is left uninitialized.
+   *
+   * @param[in] handle Handle to an object
+   * @return UnderlineSpan handle or an uninitialized handle
+   */
+  static UnderlineSpan DownCast(BaseHandle handle);
+
+public: //Methods
+  /**
+   * @brief Retrive the type of line.
+   *
+   * @return A type value.
+   */
+  const Text::Underline::Type GetType() const;
+
+  /**
+   * @brief Retrieve whether the type is defined.
+   *
+   * @return The return is true if type is defined, otherwise false.
+   */
+  bool IsTypeDefined() const;
+
+  /**
+   * @brief Retrive the color of line.
+   *
+   * @return A color value.
+   */
+  const Vector4 GetColor() const;
+
+  /**
+   * @brief Retrieve whether the color is defined.
+   *
+   * @return The return is true if color is defined, otherwise false.
+   */
+  bool IsColorDefined() const;
+
+  /**
+   * @brief Retrive the height of line.
+   *
+   * @return A height value.
+   */
+  const float GetHeight() const;
+
+  /**
+   * @brief Retrieve whether the height is defined.
+   *
+   * @return The return is true if height is defined, otherwise false.
+   */
+  bool IsHeightDefined() const;
+
+  /**
+   * @brief Retrive the dash-gap of line.
+   *
+   * @return A dash-gap value.
+   */
+  const float GetDashGap() const;
+
+  /**
+   * @brief Retrieve whether the dash-gap is defined.
+   *
+   * @return The return is true if dash-gap is defined, otherwise false.
+   */
+  bool IsDashGapDefined() const;
+
+  /**
+   * @brief Retrive the dash-width of line.
+   *
+   * @return A dash-width value.
+   */
+  const float GetDashWidth() const;
+
+  /**
+   * @brief Retrieve whether the dash-width is defined.
+   *
+   * @return The return is true if dash-width is defined, otherwise false.
+   */
+  bool IsDashWidthDefined() const;
+
+public: // Not intended for application developers
+  /// @cond internal
+  /**
+   * @brief This constructor is used internally to Create an initialized UnderlineSpan handle.
+   *
+   * @param[in] underlineSpan Pointer to internal UnderlineSpan
+   */
+  explicit DALI_INTERNAL UnderlineSpan(Internal::UnderlineSpan* underlineSpan);
+  /// @endcond
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_UNDERLINE_SPAN_H
index 96d2a53..0ffdbfc 100644 (file)
@@ -163,6 +163,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/spannable/spans/base-span-impl.cpp
    ${toolkit_src_dir}/text/spannable/spans/foreground-color-span-impl.cpp
    ${toolkit_src_dir}/text/spannable/spans/font-span-impl.cpp
+   ${toolkit_src_dir}/text/spannable/spans/underline-span-impl.cpp
    ${toolkit_src_dir}/text/spannable/span-ranges-container-impl.cpp
    ${toolkit_src_dir}/text/hyphenator.cpp
    ${toolkit_src_dir}/text/text-enumerations-impl.cpp
index ff4697b..d29ac70 100644 (file)
@@ -387,7 +387,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -428,7 +429,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mLogicalModel->mColorRuns.PushBack(colorRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -443,7 +445,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -464,7 +467,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -485,7 +489,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -506,7 +511,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -527,7 +533,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
           impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
 
           //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+             impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
           {
             impl.CopyUnderlinedFromLogicalToVisualModels(false);
           }
@@ -575,7 +582,8 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o
        (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count())))
   {
     //Mark-up processor case
-    if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+    if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled() ||
+       impl.mModel->mLogicalModel->mUnderlineRunsUpdated)
     {
       impl.CopyUnderlinedFromLogicalToVisualModels(true);
       impl.CopyStrikethroughFromLogicalToVisualModels();
index 8b6d8cb..46d9263 100644 (file)
@@ -1721,6 +1721,9 @@ void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearP
 
     mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
   }
+
+  // Reset flag. The updates have been applied from logical to visual.
+  mModel->mLogicalModel->mUnderlineRunsUpdated = false;
 }
 
 void Controller::Impl::CopyStrikethroughFromLogicalToVisualModels()
index a4e5db2..123d8ea 100644 (file)
@@ -659,7 +659,8 @@ LogicalModel::~LogicalModel()
 
 LogicalModel::LogicalModel()
 : mBidirectionalLineIndex(0u),
-  mSpannedTextPlaced(false)
+  mSpannedTextPlaced(false),
+  mUnderlineRunsUpdated(false)
 {
 }
 
index ba67488..546e308 100644 (file)
@@ -263,6 +263,8 @@ public:
 
   BidirectionalLineRunIndex mBidirectionalLineIndex; ///< The last fetched bidirectional line info.
   bool                      mSpannedTextPlaced : 1;  ///< Whether the spanned-text is placed.
+
+  bool mUnderlineRunsUpdated : 1; /// Whether the UnderlinedCharacterRuns is updated. (Added for SpannedText)
 };
 
 } // namespace Text
diff --git a/dali-toolkit/internal/text/spannable/spans/underline-span-impl.cpp b/dali-toolkit/internal/text/spannable/spans/underline-span-impl.cpp
new file mode 100644 (file)
index 0000000..32d219f
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/spannable/spans/underline-span-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace Internal
+{
+struct UnderlineSpan::Impl
+{
+  UnderlineStyleProperties mUnderlineProperties; ///< The properties of underline style.
+};
+
+UnderlineSpan::UnderlineSpan()
+: BaseSpan()
+{
+  mImpl = std::make_unique<Impl>();
+}
+
+UnderlineSpan ::~UnderlineSpan()
+{
+}
+
+Dali::Toolkit::Text::UnderlineSpan UnderlineSpan::New()
+{
+  UnderlineSpanPtr object = new UnderlineSpan();
+
+  Dali::Toolkit::Text::UnderlineSpan handle = Dali::Toolkit::Text::UnderlineSpan(object.Get());
+
+  return handle;
+}
+
+Dali::Toolkit::Text::UnderlineSpan UnderlineSpan::NewSolid(Vector4 color, float height)
+{
+  UnderlineSpanPtr object = new UnderlineSpan();
+  object->SetType(Text::Underline::SOLID);
+  object->SetColor(color);
+  object->SetHeight(height);
+
+  Dali::Toolkit::Text::UnderlineSpan handle = Dali::Toolkit::Text::UnderlineSpan(object.Get());
+
+  return handle;
+}
+
+Dali::Toolkit::Text::UnderlineSpan UnderlineSpan::NewDashed(Vector4 color, float height, float dashGap, float dashWidth)
+{
+  UnderlineSpanPtr object = new UnderlineSpan();
+  object->SetType(Text::Underline::DASHED);
+  object->SetColor(color);
+  object->SetHeight(height);
+  object->SetDashGap(dashGap);
+  object->SetDashWidth(dashWidth);
+
+  Dali::Toolkit::Text::UnderlineSpan handle = Dali::Toolkit::Text::UnderlineSpan(object.Get());
+
+  return handle;
+}
+
+Dali::Toolkit::Text::UnderlineSpan UnderlineSpan::NewDouble(Vector4 color, float height)
+{
+  UnderlineSpanPtr object = new UnderlineSpan();
+  object->SetType(Text::Underline::DOUBLE);
+  object->SetColor(color);
+  object->SetHeight(height);
+
+  Dali::Toolkit::Text::UnderlineSpan handle = Dali::Toolkit::Text::UnderlineSpan(object.Get());
+
+  return handle;
+}
+
+//Methods
+
+const Text::Underline::Type UnderlineSpan::GetType() const
+{
+  return mImpl->mUnderlineProperties.type;
+}
+
+bool UnderlineSpan::IsTypeDefined() const
+{
+  return mImpl->mUnderlineProperties.typeDefined;
+}
+
+void UnderlineSpan::SetType(const Text::Underline::Type& type)
+{
+  mImpl->mUnderlineProperties.type        = type;
+  mImpl->mUnderlineProperties.typeDefined = true;
+}
+
+const Vector4 UnderlineSpan::GetColor() const
+{
+  return mImpl->mUnderlineProperties.color;
+}
+
+bool UnderlineSpan::IsColorDefined() const
+{
+  return mImpl->mUnderlineProperties.colorDefined;
+}
+
+void UnderlineSpan::SetColor(const Vector4& color)
+{
+  mImpl->mUnderlineProperties.color        = color;
+  mImpl->mUnderlineProperties.colorDefined = true;
+}
+
+const float UnderlineSpan::GetHeight() const
+{
+  return mImpl->mUnderlineProperties.height;
+}
+
+bool UnderlineSpan::IsHeightDefined() const
+{
+  return mImpl->mUnderlineProperties.heightDefined;
+}
+
+void UnderlineSpan::SetHeight(const float& height)
+{
+  mImpl->mUnderlineProperties.height        = height;
+  mImpl->mUnderlineProperties.heightDefined = true;
+}
+
+const float UnderlineSpan::GetDashGap() const
+{
+  return mImpl->mUnderlineProperties.dashGap;
+}
+
+bool UnderlineSpan::IsDashGapDefined() const
+{
+  return mImpl->mUnderlineProperties.dashGapDefined;
+}
+
+void UnderlineSpan::SetDashGap(const float& dashGap)
+{
+  mImpl->mUnderlineProperties.dashGap        = dashGap;
+  mImpl->mUnderlineProperties.dashGapDefined = true;
+}
+
+const float UnderlineSpan::GetDashWidth() const
+{
+  return mImpl->mUnderlineProperties.dashWidth;
+}
+
+bool UnderlineSpan::IsDashWidthDefined() const
+{
+  return mImpl->mUnderlineProperties.dashWidthDefined;
+}
+
+void UnderlineSpan::SetDashWidth(const float& dashWidth)
+{
+  mImpl->mUnderlineProperties.dashWidth        = dashWidth;
+  mImpl->mUnderlineProperties.dashWidthDefined = true;
+}
+
+void UnderlineSpan::CreateStyleCharacterRun(IntrusivePtr<LogicalModel>& logicalModel, const Dali::Toolkit::Text::Range& range) const
+{
+  UnderlinedCharacterRun underlinedCharacterRun;
+  underlinedCharacterRun.characterRun.characterIndex     = range.GetStartIndex();
+  underlinedCharacterRun.characterRun.numberOfCharacters = range.GetNumberOfIndices();
+
+  underlinedCharacterRun.properties = mImpl->mUnderlineProperties;
+  logicalModel->mUnderlinedCharacterRuns.PushBack(underlinedCharacterRun);
+
+  logicalModel->mUnderlineRunsUpdated = true;
+}
+
+} // namespace Internal
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/spannable/spans/underline-span-impl.h b/dali-toolkit/internal/text/spannable/spans/underline-span-impl.h
new file mode 100644 (file)
index 0000000..9761979
--- /dev/null
@@ -0,0 +1,229 @@
+#ifndef DALI_TOOLKIT_INTERNAL_TEXT_UNDERLINE_SPAN_IMPL_H
+#define DALI_TOOLKIT_INTERNAL_TEXT_UNDERLINE_SPAN_IMPL_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/text/spans/underline-span.h>
+#include <memory>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/logical-model-impl.h>
+#include <dali-toolkit/internal/text/spannable/spans/base-span-impl.h>
+#include <dali/public-api/math/vector4.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace Internal
+{
+class UnderlineSpan;
+using UnderlineSpanPtr = IntrusivePtr<UnderlineSpan>;
+
+/**
+ * @copydoc Dali::Toolkit::Text::UnderlineSpan
+ */
+class UnderlineSpan : public BaseSpan
+{
+public:
+  /**
+   * @brief Creates a new UnderlineSpan object.
+   *
+   * @return A new UnderlineSpan object.
+   */
+  static Dali::Toolkit::Text::UnderlineSpan New();
+
+  /**
+   * @brief Creates a new UnderlineSpan object.
+   *
+   * @param[in] color The color of line.
+   * @param[in] height The height of line.
+   *
+   * @return A new UnderlineSpan object.
+   */
+  static Dali::Toolkit::Text::UnderlineSpan NewSolid(Vector4 color, float height);
+
+  /**
+   *
+   * @param[in] color The color of line.
+   * @param[in] height The height of line.
+   * @param[in] dashGap The dash-gap of line.
+   * @param[in] dashWidth The dash-width of line.
+   *
+   * @return A new UnderlineSpan object.
+   */
+  static Dali::Toolkit::Text::UnderlineSpan NewDashed(Vector4 color, float height, float dashGap, float dashWidth);
+
+  /**
+   * @brief Creates a new UnderlineSpan object.
+   *
+   * @param[in] color The color of line.
+   * @param[in] height The height of line.
+   *
+   * @return A new UnderlineSpan object.
+   */
+  static Dali::Toolkit::Text::UnderlineSpan NewDouble(Vector4 color, float height);
+
+  /**
+   * Default Constructor
+   */
+  UnderlineSpan();
+
+  UnderlineSpan(const UnderlineSpan&) = delete;            ///< Deleted copy constructor
+  UnderlineSpan(UnderlineSpan&&)      = delete;            ///< Deleted move constructor
+  UnderlineSpan& operator=(const UnderlineSpan&) = delete; ///< Deleted copy assignment operator
+  UnderlineSpan& operator=(UnderlineSpan&&) = delete;      ///< Deleted move assignment operator
+
+  /**
+   * @brief Destructor
+   *
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  ~UnderlineSpan() override;
+
+public: //Methods
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::GetType()
+   */
+  const Text::Underline::Type GetType() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::IsTypeDefined()
+   */
+  bool IsTypeDefined() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::GetColor()
+   */
+  const Vector4 GetColor() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::IsColorDefined()
+   */
+  bool IsColorDefined() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::GetHeight()
+   */
+  const float GetHeight() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::IsHeightDefined()
+   */
+  bool IsHeightDefined() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::GetDashGap()
+   */
+  const float GetDashGap() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::IsDashGapDefined()
+   */
+  bool IsDashGapDefined() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::GetDashWidth()
+   */
+  const float GetDashWidth() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::UnderlineSpan::IsDashWidthDefined()
+   */
+  bool IsDashWidthDefined() const;
+
+public: //Methods. Not intended for application developers
+  /**
+   * @brief Set the type of underline.
+   *
+   * @param[in] type The type of line.
+   */
+  void SetType(const Text::Underline::Type& type);
+
+  /**
+   * @brief Set the color of underline.
+   *
+   * @param[in] color The color of line.
+   */
+  void SetColor(const Vector4& color);
+
+  /**
+   * @brief Set the height of underline.
+   *
+   * @param[in] height The height of line.
+   */
+  void SetHeight(const float& height);
+
+  /**
+   * @brief Set the dash-gap of underline.
+   *
+   * @param[in] dashGap The dash-gap of line.
+   */
+  void SetDashGap(const float& dashGap);
+
+  /**
+    * @brief Set the dash-width of underline.
+    *
+    * @param[in] dashWidth The dash-width of line.
+    */
+  void SetDashWidth(const float& dashWidth);
+
+public: //Methods for internal only
+        /**
+   * @copydoc Dali::Toolkit::Text::BaseSpan::CreateStyleCharacterRun
+   */
+  void CreateStyleCharacterRun(IntrusivePtr<LogicalModel>& logicalModel, const Dali::Toolkit::Text::Range& range) const override;
+
+private:
+  struct Impl;
+  std::unique_ptr<Impl> mImpl{nullptr};
+
+}; // class UnderlineSpan
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::UnderlineSpan& GetImplementation(Dali::Toolkit::Text::UnderlineSpan& underlineSpan)
+{
+  DALI_ASSERT_ALWAYS(underlineSpan && "underlineSpan handle is empty");
+
+  BaseObject& object = underlineSpan.GetBaseObject();
+
+  return static_cast<Internal::UnderlineSpan&>(object);
+}
+
+inline const Internal::UnderlineSpan& GetImplementation(const Dali::Toolkit::Text::UnderlineSpan& underlineSpan)
+{
+  DALI_ASSERT_ALWAYS(underlineSpan && "underlineSpan handle is empty");
+
+  const BaseObject& object = underlineSpan.GetBaseObject();
+
+  return static_cast<const Internal::UnderlineSpan&>(object);
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_TEXT_UNDERLINE_SPAN_IMPL_H
\ No newline at end of file