Merge "Add support for span tag" into devel/master
authorBowon Ryu <bowon.ryu@samsung.com>
Mon, 28 Jun 2021 07:47:56 +0000 (07:47 +0000)
committerGerrit Code Review <gerrit@review>
Mon, 28 Jun 2021 07:47:56 +0000 (07:47 +0000)
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
dali-toolkit/internal/file.list
dali-toolkit/internal/text/markup-processor-color.cpp
dali-toolkit/internal/text/markup-processor-color.h
dali-toolkit/internal/text/markup-processor-font.cpp
dali-toolkit/internal/text/markup-processor-font.h
dali-toolkit/internal/text/markup-processor-span.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor-span.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor.cpp

index 73d9e12..09c5078 100755 (executable)
@@ -198,4 +198,68 @@ int UtcDaliTextEditorBackgroundTag(void)
   DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, TEST_LOCATION);
 
   END_TEST;
+}
+
+int UtcDaliTextEditorTextWithSpan(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliTextEditorTextWithSpan\n");
+
+  TextEditor editor = TextEditor::New();
+  DALI_TEST_CHECK( editor );
+
+  editor.SetProperty( TextEditor ::Property::ENABLE_MARKUP,  true );
+  editor.SetProperty( TextEditor::Property::TEXT, "Hello Span" );
+  application.GetScene().Add( editor );
+
+  application.SendNotification();
+  application.Render();
+
+  Vector3 originalSize = editor.GetNaturalSize();
+  editor.SetProperty( TextEditor::Property::TEXT, "H<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red'>ello</span> Span" );
+
+  application.SendNotification();
+  application.Render();
+
+  Vector3 spanSize = editor.GetNaturalSize();
+
+  DALI_TEST_GREATER(spanSize.width, originalSize.width, TEST_LOCATION);
+
+  Toolkit::Internal::TextEditor& editorImpl = GetImpl( editor );
+  const ColorIndex* const colorIndicesBuffer1 = editorImpl.getController()->GetTextModel()->GetColorIndices();
+
+  DALI_TEST_CHECK( colorIndicesBuffer1 );
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer1[0], 0u, TEST_LOCATION);
+
+  //span color
+  DALI_TEST_EQUALS( colorIndicesBuffer1[1], 1u, TEST_LOCATION);
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer1[6], 0u, TEST_LOCATION);
+
+
+  editor.SetProperty( TextEditor::Property::TEXT, "<span font-size='45'>H</span>ello <span text-color='red'>S</span>pan" );
+
+  application.SendNotification();
+  application.Render();
+
+  const ColorIndex* const colorIndicesBuffer2 = editorImpl.getController()->GetTextModel()->GetColorIndices();
+
+  DALI_TEST_CHECK( colorIndicesBuffer2 );
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer2[0], 0u, TEST_LOCATION);
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer2[1], 0u, TEST_LOCATION);
+
+  //span color
+  DALI_TEST_EQUALS( colorIndicesBuffer2[6], 1u, TEST_LOCATION);
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer2[7], 0u, TEST_LOCATION);
+
+  END_TEST;
 }
\ No newline at end of file
index 73fe7e2..1fbc13e 100755 (executable)
@@ -282,4 +282,68 @@ int UtcDaliTextFieldBackgroundTag(void)
   DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, TEST_LOCATION);
 
   END_TEST;
+}
+
+int UtcDaliTextFieldTextWithSpan(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliTextFieldTextWithSpan\n");
+
+  TextField field = TextField::New();
+  DALI_TEST_CHECK( field );
+
+  field.SetProperty( TextField ::Property::ENABLE_MARKUP,  true );
+  field.SetProperty( TextField::Property::TEXT, "Hello Span" );
+  application.GetScene().Add( field );
+
+  application.SendNotification();
+  application.Render();
+
+  Vector3 originalSize = field.GetNaturalSize();
+  field.SetProperty( TextField::Property::TEXT, "H<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red'>ello</span> Span" );
+
+  application.SendNotification();
+  application.Render();
+
+  Vector3 spanSize = field.GetNaturalSize();
+
+  DALI_TEST_GREATER(spanSize.width, originalSize.width, TEST_LOCATION);
+
+  Toolkit::Internal::TextField& fieldImpl = GetImpl( field );
+  const ColorIndex* const colorIndicesBuffer1 = fieldImpl.getController()->GetTextModel()->GetColorIndices();
+
+  DALI_TEST_CHECK( colorIndicesBuffer1 );
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer1[0], 0u, TEST_LOCATION);
+
+  //span color
+  DALI_TEST_EQUALS( colorIndicesBuffer1[1], 1u, TEST_LOCATION);
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer1[6], 0u, TEST_LOCATION);
+
+
+  field.SetProperty( TextField::Property::TEXT, "<span font-size='45'>H</span>ello <span text-color='red'>S</span>pan" );
+
+  application.SendNotification();
+  application.Render();
+
+  const ColorIndex* const colorIndicesBuffer2 = fieldImpl.getController()->GetTextModel()->GetColorIndices();
+
+  DALI_TEST_CHECK( colorIndicesBuffer2 );
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer2[0], 0u, TEST_LOCATION);
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer2[1], 0u, TEST_LOCATION);
+
+  //span color
+  DALI_TEST_EQUALS( colorIndicesBuffer2[6], 1u, TEST_LOCATION);
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer2[7], 0u, TEST_LOCATION);
+
+  END_TEST;
 }
\ No newline at end of file
index f67d88a..e03fec1 100755 (executable)
@@ -97,4 +97,68 @@ int UtcDaliTextLabelBackgroundTag(void)
   DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, TEST_LOCATION);
 
   END_TEST;
+}
+
+int UtcDaliTextLabelTextWithSpan(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliTextLabelTextWithSpan\n");
+
+  TextLabel label = TextLabel::New();
+  DALI_TEST_CHECK( label );
+
+  label.SetProperty( TextLabel ::Property::ENABLE_MARKUP,  true );
+  label.SetProperty( TextLabel::Property::TEXT, "Hello Span" );
+  application.GetScene().Add( label );
+
+  application.SendNotification();
+  application.Render();
+
+  Vector3 originalSize = label.GetNaturalSize();
+  label.SetProperty( TextLabel::Property::TEXT, "H<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red'>ello</span> Span" );
+
+  application.SendNotification();
+  application.Render();
+
+  Vector3 spanSize = label.GetNaturalSize();
+
+  DALI_TEST_GREATER(spanSize.width, originalSize.width, TEST_LOCATION);
+
+  Toolkit::Internal::TextLabel& labelImpl = GetImpl( label );
+  const ColorIndex* const colorIndicesBuffer1 = labelImpl.getController()->GetTextModel()->GetColorIndices();
+
+  DALI_TEST_CHECK( colorIndicesBuffer1 );
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer1[0], 0u, TEST_LOCATION);
+
+  //span color
+  DALI_TEST_EQUALS( colorIndicesBuffer1[1], 1u, TEST_LOCATION);
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer1[6], 0u, TEST_LOCATION);
+
+
+  label.SetProperty( TextLabel::Property::TEXT, "<span font-size='45'>H</span>ello <span text-color='red'>S</span>pan" );
+
+  application.SendNotification();
+  application.Render();
+
+  const ColorIndex* const colorIndicesBuffer2 = labelImpl.getController()->GetTextModel()->GetColorIndices();
+
+  DALI_TEST_CHECK( colorIndicesBuffer2 );
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer2[0], 0u, TEST_LOCATION);
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer2[1], 0u, TEST_LOCATION);
+
+  //span color
+  DALI_TEST_EQUALS( colorIndicesBuffer2[6], 1u, TEST_LOCATION);
+
+  //default color
+  DALI_TEST_EQUALS( colorIndicesBuffer2[7], 0u, TEST_LOCATION);
+
+  END_TEST;
 }
\ No newline at end of file
index f712e9f..41d9978 100644 (file)
@@ -137,6 +137,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/markup-processor-anchor.cpp
    ${toolkit_src_dir}/text/markup-processor-font.cpp
    ${toolkit_src_dir}/text/markup-processor-background.cpp
+   ${toolkit_src_dir}/text/markup-processor-span.cpp
    ${toolkit_src_dir}/text/markup-processor-helper-functions.cpp
    ${toolkit_src_dir}/text/multi-language-support.cpp
    ${toolkit_src_dir}/text/hidden-text.cpp
index b66e37a..d5fce04 100644 (file)
@@ -36,6 +36,11 @@ namespace
 const std::string XHTML_VALUE_ATTRIBUTE("value");
 }
 
+void ProcessColor(const Attribute& attribute, ColorRun& colorRun)
+{
+  ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color);
+}
+
 void ProcessColorTag(const Tag& tag, ColorRun& colorRun)
 {
   for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
@@ -46,7 +51,7 @@ void ProcessColorTag(const Tag& tag, ColorRun& colorRun)
     const Attribute& attribute(*it);
     if(TokenComparison(XHTML_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
     {
-      ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color);
+      ProcessColor(attribute, colorRun);
     }
   }
 }
index 89e9d2a..02210fb 100644 (file)
@@ -25,11 +25,20 @@ namespace Toolkit
 namespace Text
 {
 struct Tag;
+struct Attribute;
 struct ColorRun;
 
 /**
  * @brief Retrieves the color value from the tag and sets it to the color run.
  *
+ * @param[in] attribute the color attribute.
+ * @param[in,out] colorRun The color run.
+ */
+void ProcessColor(const Attribute& attribute, ColorRun& colorRun);
+
+/**
+ * @brief Retrieves the color value from the tag and sets it to the color run.
+ *
  * @param[in] tag The color tag and its attributes.
  * @param[in,out] colorRun The color run.
  */
index 4ddcd61..df8b6ec 100644 (file)
@@ -41,9 +41,64 @@ const std::string XHTML_WEIGHT_ATTRIBUTE("weight");
 const std::string XHTML_WIDTH_ATTRIBUTE("width");
 const std::string XHTML_SLANT_ATTRIBUTE("slant");
 
-const unsigned int MAX_FONT_ATTRIBUTE_SIZE = 15u; ///< The maximum length of any of the possible 'weight', 'width' or 'slant' values.
+const std::string  FONT_PREFIX("font-");
+const unsigned int FONT_PREFIX_LENGTH      = 5u;
+const unsigned int MIN_FONT_ATTRIBUTE_SIZE = 4u;   ///< The minimum length of any of the possible 'weight', 'width' , 'slant' or 'size' values.
+const unsigned int MAX_FONT_ATTRIBUTE_SIZE = 15u;  ///< The maximum length of any of the possible 'weight', 'width' or 'slant' values.
+const float        PIXEL_FORMAT_64_FACTOR  = 64.f; ///< 64.f is used to convert from point size to 26.6 pixel format.
 } // namespace
 
+void processFontAttributeValue(char value[], const Attribute& attribute)
+{
+  // The StringToWeight() uses the Scripting::GetEnumeration() function which requires the input string to end with a '\0' char.
+  const Length length = attribute.valueLength > MAX_FONT_ATTRIBUTE_SIZE ? MAX_FONT_ATTRIBUTE_SIZE : attribute.valueLength;
+  memcpy(value, attribute.valueBuffer, length);
+  value[length] = 0;
+}
+
+void ProcessFontFamily(const Attribute& attribute, FontDescriptionRun& fontRun)
+{
+  fontRun.familyDefined = true;
+  fontRun.familyLength  = attribute.valueLength;
+  fontRun.familyName    = new char[fontRun.familyLength];
+  memcpy(fontRun.familyName, attribute.valueBuffer, fontRun.familyLength);
+  // The memory is freed when the font run is removed from the logical model.
+}
+
+void ProcessFontSize(const Attribute& attribute, FontDescriptionRun& fontRun)
+{
+  // 64.f is used to convert from point size to 26.6 pixel format.
+  fontRun.size        = static_cast<PointSize26Dot6>(StringToFloat(attribute.valueBuffer) * PIXEL_FORMAT_64_FACTOR);
+  fontRun.sizeDefined = true;
+}
+
+void ProcessFontWeight(const Attribute& attribute, FontDescriptionRun& fontRun)
+{
+  char value[MAX_FONT_ATTRIBUTE_SIZE + 1u];
+  processFontAttributeValue(value, attribute);
+
+  fontRun.weight        = StringToWeight(value);
+  fontRun.weightDefined = true;
+}
+
+void ProcessFontWidth(const Attribute& attribute, FontDescriptionRun& fontRun)
+{
+  char value[MAX_FONT_ATTRIBUTE_SIZE + 1u];
+  processFontAttributeValue(value, attribute);
+
+  fontRun.width        = StringToWidth(value);
+  fontRun.widthDefined = true;
+}
+
+void ProcessFontSlant(const Attribute& attribute, FontDescriptionRun& fontRun)
+{
+  char value[MAX_FONT_ATTRIBUTE_SIZE + 1u];
+  processFontAttributeValue(value, attribute);
+
+  fontRun.slant        = StringToSlant(value);
+  fontRun.slantDefined = true;
+}
+
 void ProcessFontTag(const Tag& tag, FontDescriptionRun& fontRun)
 {
   for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
@@ -52,52 +107,26 @@ void ProcessFontTag(const Tag& tag, FontDescriptionRun& fontRun)
       ++it)
   {
     const Attribute& attribute(*it);
+
     if(TokenComparison(XHTML_FAMILY_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
     {
-      fontRun.familyDefined = true;
-      fontRun.familyLength  = attribute.valueLength;
-      fontRun.familyName    = new char[fontRun.familyLength];
-      memcpy(fontRun.familyName, attribute.valueBuffer, fontRun.familyLength);
-      // The memory is freed when the font run is removed from the logical model.
+      ProcessFontFamily(attribute, fontRun);
     }
     else if(TokenComparison(XHTML_SIZE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
     {
-      // 64.f is used to convert from point size to 26.6 pixel format.
-      fontRun.size        = static_cast<PointSize26Dot6>(StringToFloat(attribute.valueBuffer) * 64.f);
-      fontRun.sizeDefined = true;
+      ProcessFontSize(attribute, fontRun);
     }
     else if(TokenComparison(XHTML_WEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
     {
-      // The StringToWeight() uses the Scripting::GetEnumeration() function which requires the input string to end with a '\0' char.
-      char         value[MAX_FONT_ATTRIBUTE_SIZE + 1u];
-      const Length length = attribute.valueLength > MAX_FONT_ATTRIBUTE_SIZE ? MAX_FONT_ATTRIBUTE_SIZE : attribute.valueLength;
-      memcpy(value, attribute.valueBuffer, length);
-      value[length] = 0;
-
-      fontRun.weight        = StringToWeight(value);
-      fontRun.weightDefined = true;
+      ProcessFontWeight(attribute, fontRun);
     }
     else if(TokenComparison(XHTML_WIDTH_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
     {
-      // The StringToWidth() uses the Scripting::GetEnumeration() function which requires the input string to end with a '\0' char.
-      char         value[MAX_FONT_ATTRIBUTE_SIZE + 1u];
-      const Length length = attribute.valueLength > MAX_FONT_ATTRIBUTE_SIZE ? MAX_FONT_ATTRIBUTE_SIZE : attribute.valueLength;
-      memcpy(value, attribute.valueBuffer, length);
-      value[length] = 0;
-
-      fontRun.width        = StringToWidth(value);
-      fontRun.widthDefined = true;
+      ProcessFontWidth(attribute, fontRun);
     }
     else if(TokenComparison(XHTML_SLANT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
     {
-      // The StringToSlant() uses the Scripting::GetEnumeration() function which requires the input string to end with a '\0' char.
-      char         value[MAX_FONT_ATTRIBUTE_SIZE + 1u];
-      const Length length = attribute.valueLength > MAX_FONT_ATTRIBUTE_SIZE ? MAX_FONT_ATTRIBUTE_SIZE : attribute.valueLength;
-      memcpy(value, attribute.valueBuffer, length);
-      value[length] = 0;
-
-      fontRun.slant        = StringToSlant(value);
-      fontRun.slantDefined = true;
+      ProcessFontSlant(attribute, fontRun);
     }
   }
 }
index 8b075bf..6461451 100644 (file)
@@ -25,6 +25,7 @@ namespace Toolkit
 namespace Text
 {
 struct Tag;
+struct Attribute;
 struct FontDescriptionRun;
 
 /**
@@ -35,6 +36,46 @@ struct FontDescriptionRun;
  */
 void ProcessFontTag(const Tag& tag, FontDescriptionRun& fontRun);
 
+/**
+ * @brief Fill the font run with the font slant attribute value.
+ *
+ * @param[in] attribute the font slant attribute.
+ * @param[out] fontRun The font description run.
+ */
+void ProcessFontSlant(const Attribute& attribute, FontDescriptionRun& fontRun);
+
+/**
+ * @brief Fill the font run with the font width attribute value.
+ *
+ * @param[in] attribute the font width attribute.
+ * @param[out] fontRun The font description run.
+ */
+void ProcessFontWidth(const Attribute& attribute, FontDescriptionRun& fontRun);
+
+/**
+ * @brief Fill the font run with the font weight attribute value.
+ *
+ * @param[in] attribute the font weight attribute.
+ * @param[out] fontRun The font description run.
+ */
+void ProcessFontWeight(const Attribute& attribute, FontDescriptionRun& fontRun);
+
+/**
+ * @brief Fill the font run with the font size attribute value.
+ *
+ * @param[in] attribute the font size attribute.
+ * @param[out] fontRun The font description run.
+ */
+void ProcessFontSize(const Attribute& attribute, FontDescriptionRun& fontRun);
+
+/**
+ * @brief Fill the font run with the font family attribute value.
+ *
+ * @param[in] attribute the font family attribute.
+ * @param[out] fontRun The font description run.
+ */
+void ProcessFontFamily(const Attribute& attribute, FontDescriptionRun& fontRun);
+
 } // namespace Text
 
 } // namespace Toolkit
diff --git a/dali-toolkit/internal/text/markup-processor-span.cpp b/dali-toolkit/internal/text/markup-processor-span.cpp
new file mode 100644 (file)
index 0000000..40a508d
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor-color.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/markup-processor-font.h>
+#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace
+{
+const std::string XHTML_FAMILY_ATTRIBUTE("font-family");
+const std::string XHTML_SIZE_ATTRIBUTE("font-size");
+const std::string XHTML_WEIGHT_ATTRIBUTE("font-weight");
+const std::string XHTML_WIDTH_ATTRIBUTE("font-width");
+const std::string XHTML_SLANT_ATTRIBUTE("font-slant");
+
+const std::string XHTML_COLOR_ATTRIBUTE("text-color");
+} // namespace
+
+void ProcessSpanTag(const Tag& tag, ColorRun& colorRun, FontDescriptionRun& fontRun, bool& isColorDefined, bool& isFontDefined)
+{
+  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
+                                       endIt = tag.attributes.End();
+      it != endIt;
+      ++it)
+  {
+    const Attribute& attribute(*it);
+
+    if(TokenComparison(XHTML_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isColorDefined = true;
+      ProcessColor(attribute, colorRun);
+    }
+    else if(TokenComparison(XHTML_FAMILY_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isFontDefined = true;
+      ProcessFontFamily(attribute, fontRun);
+    }
+    else if(TokenComparison(XHTML_SIZE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isFontDefined = true;
+      ProcessFontSize(attribute, fontRun);
+    }
+    else if(TokenComparison(XHTML_WEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isFontDefined = true;
+      ProcessFontWeight(attribute, fontRun);
+    }
+    else if(TokenComparison(XHTML_WIDTH_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isFontDefined = true;
+      ProcessFontWidth(attribute, fontRun);
+    }
+    else if(TokenComparison(XHTML_SLANT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isFontDefined = true;
+      ProcessFontSlant(attribute, fontRun);
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-span.h b/dali-toolkit/internal/text/markup-processor-span.h
new file mode 100644 (file)
index 0000000..330caf1
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_SPAN_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_SPAN_H
+
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Tag;
+struct MarkupProcessData;
+
+/**
+ * @brief process the span from the tag and process all styles in it.
+ *
+ * @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] isColorDefined if the span has color defined.
+ * @param[out] isFontDefined if the span has font defined.
+ */
+void ProcessSpanTag(const Tag& tag, ColorRun& colorRun, FontDescriptionRun& fontRun, bool& isColorDefined, bool& isFontDefined);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_SPAN_H
index 6fef092..b656aa4 100644 (file)
@@ -31,6 +31,7 @@
 #include <dali-toolkit/internal/text/markup-processor-embedded-item.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-span.h>
 #include <dali-toolkit/internal/text/xhtml-entities.h>
 
 namespace Dali
@@ -55,6 +56,7 @@ const std::string XHTML_OUTLINE_TAG("outline");
 const std::string XHTML_ITEM_TAG("item");
 const std::string XHTML_ANCHOR_TAG("a");
 const std::string XHTML_BACKGROUND_TAG("background");
+const std::string XHTML_SPAN_TAG("span");
 
 const char LESS_THAN      = '<';
 const char GREATER_THAN   = '>';
@@ -82,15 +84,16 @@ const unsigned int DEFAULT_VECTOR_SIZE   = 16u; ///< Default size of run vectors
 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_MARKUP_PROCESSOR");
 #endif
 
+typedef VectorBase::SizeType RunIndex;
+
 /**
  * @brief Struct used to retrieve the style runs from the mark-up string.
  */
+template<typename StyleStackType>
 struct StyleStack
 {
-  typedef VectorBase::SizeType RunIndex;
-
-  Vector<RunIndex> stack;    ///< Use a vector as a style stack. Stores the indices pointing where the run is stored inside the logical model.
-  unsigned int     topIndex; ///< Points the top of the stack.
+  Vector<StyleStackType> stack;    ///< Use a vector as a style stack.
+  unsigned int           topIndex; ///< Points the top of the stack.
 
   StyleStack()
   : stack(),
@@ -99,7 +102,7 @@ struct StyleStack
     stack.Resize(DEFAULT_VECTOR_SIZE);
   }
 
-  void Push(RunIndex index)
+  void Push(StyleStackType item)
   {
     // Check if there is space inside the style stack.
     const VectorBase::SizeType size = stack.Count();
@@ -109,14 +112,14 @@ struct StyleStack
       stack.Resize(2u * size);
     }
 
-    // Set the run index in the top of the stack.
-    *(stack.Begin() + topIndex) = index;
+    // Set the item in the top of the stack.
+    *(stack.Begin() + topIndex) = item;
 
     // Reposition the pointer to the top of the stack.
     ++topIndex;
   }
 
-  RunIndex Pop()
+  StyleStackType Pop()
   {
     // Pop the top of the stack.
     --topIndex;
@@ -125,6 +128,17 @@ struct StyleStack
 };
 
 /**
+ * @brief Struct used to retrieve spans from the mark-up string.
+ */
+struct Span
+{
+  RunIndex colorRunIndex;
+  RunIndex fontRunIndex;
+  bool     isColorDefined;
+  bool     isFontDefined;
+};
+
+/**
  * @brief Initializes a font run description to its defaults.
  *
  * @param[in,out] fontRun The font description run to initialize.
@@ -169,6 +183,19 @@ void Initialize(UnderlinedCharacterRun& underlinedCharacterRun)
 }
 
 /**
+ * @brief Initializes a span to its defaults.
+ *
+ * @param[in,out] span The span to be initialized.
+ */
+void Initialize(Span& span)
+{
+  span.colorRunIndex  = 0u;
+  span.isColorDefined = false;
+  span.fontRunIndex   = 0u;
+  span.isFontDefined  = false;
+}
+
+/**
  * @brief Splits the tag string into the tag name and its attributes.
  *
  * The attributes are stored in a vector in the tag.
@@ -526,10 +553,10 @@ bool XHTMLNumericEntityToUtf8(const char* markupText, char* utf8)
 template<typename RunType>
 void ProcessTagForRun(
   Vector<RunType>&                          runsContainer,
-  StyleStack&                               styleStack,
+  StyleStack<RunIndex>&                     styleStack,
   const Tag&                                tag,
   const CharacterIndex                      characterIndex,
-  StyleStack::RunIndex&                     runIndex,
+  RunIndex&                                 runIndex,
   int&                                      tagReference,
   std::function<void(const Tag&, RunType&)> parameterSettingFunction)
 {
@@ -627,6 +654,94 @@ void ProcessAnchorTag(
 }
 
 /**
+ * @brief Processes span tag for the color-run & font-run.
+ *
+ * @param[in] spanTag The tag we are currently processing
+ * @param[in/out] spanStack The spans stack
+ * @param[int/out] colorRuns The container containing all the color runs
+ * @param[int/out] fontRuns The container containing all the font description runs
+ * @param[in/out] colorRunIndex The color run index
+ * @param[in/out] fontRunIndex The font run index
+ * @param[in] characterIndex The current character index
+ * @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)
+{
+  if(!spanTag.isEndTag)
+  {
+    // Create a new run.
+    ColorRun colorRun;
+    Initialize(colorRun);
+
+    FontDescriptionRun fontRun;
+    Initialize(fontRun);
+
+    Span span;
+    Initialize(span);
+
+    // Fill the run with the parameters.
+    colorRun.characterRun.characterIndex = characterIndex;
+    fontRun.characterRun.characterIndex  = characterIndex;
+
+    span.colorRunIndex = colorRunIndex;
+    span.fontRunIndex  = fontRunIndex;
+
+    ProcessSpanTag(spanTag, colorRun, fontRun, span.isColorDefined, span.isFontDefined);
+
+    // Push the span into the stack.
+    spanStack.Push(span);
+
+    // Point the next free run.
+    if(span.isColorDefined)
+    {
+      // Push the run in the logical model.
+      colorRuns.PushBack(colorRun);
+      ++colorRunIndex;
+    }
+
+    if(span.isFontDefined)
+    {
+      // Push the run in the logical model.
+      fontRuns.PushBack(fontRun);
+      ++fontRunIndex;
+    }
+
+    // Increase reference
+    ++tagReference;
+  }
+  else
+  {
+    if(tagReference > 0)
+    {
+      // Pop the top of the stack and set the number of characters of the run.
+      Span span = spanStack.Pop();
+
+      if(span.isColorDefined)
+      {
+        ColorRun& colorRun                       = *(colorRuns.Begin() + span.colorRunIndex);
+        colorRun.characterRun.numberOfCharacters = characterIndex - colorRun.characterRun.characterIndex;
+      }
+
+      if(span.isFontDefined)
+      {
+        FontDescriptionRun& fontRun             = *(fontRuns.Begin() + span.fontRunIndex);
+        fontRun.characterRun.numberOfCharacters = characterIndex - fontRun.characterRun.characterIndex;
+      }
+
+      --tagReference;
+    }
+  }
+}
+
+/**
  * @brief Resizes the model's vectors
  *
  * @param[in/out] markupProcessData The markup process data
@@ -635,7 +750,7 @@ void ProcessAnchorTag(
  * @param[in] underlinedCharacterRunIndex The underlined character run index
  * @param[in] backgroundRunIndex The background run index
  */
-void ResizeModelVectors(MarkupProcessData& markupProcessData, const StyleStack::RunIndex fontRunIndex, const StyleStack::RunIndex colorRunIndex, const StyleStack::RunIndex underlinedCharacterRunIndex, const StyleStack::RunIndex backgroundRunIndex)
+void ResizeModelVectors(MarkupProcessData& markupProcessData, const RunIndex fontRunIndex, const RunIndex colorRunIndex, const RunIndex underlinedCharacterRunIndex, const RunIndex backgroundRunIndex)
 {
   markupProcessData.fontRuns.Resize(fontRunIndex);
   markupProcessData.colorRuns.Resize(colorRunIndex);
@@ -754,13 +869,16 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
   markupProcessData.markupProcessedText.reserve(markupStringSize);
 
   // Stores a struct with the index to the first character of the run, the type of run and its parameters.
-  StyleStack styleStack;
+  StyleStack<RunIndex> styleStack;
+
+  // Stores a struct with the index to the first character of the color run & color font for the span.
+  StyleStack<Span> spanStack;
 
   // Points the next free position in the vector of runs.
-  StyleStack::RunIndex colorRunIndex               = 0u;
-  StyleStack::RunIndex fontRunIndex                = 0u;
-  StyleStack::RunIndex underlinedCharacterRunIndex = 0u;
-  StyleStack::RunIndex backgroundRunIndex          = 0u;
+  RunIndex colorRunIndex               = 0u;
+  RunIndex fontRunIndex                = 0u;
+  RunIndex underlinedCharacterRunIndex = 0u;
+  RunIndex backgroundRunIndex          = 0u;
 
   // check tag reference
   int colorTagReference      = 0u;
@@ -769,6 +887,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
   int bTagReference          = 0u;
   int uTagReference          = 0u;
   int backgroundTagReference = 0u;
+  int spanTagReference       = 0u;
 
   // Give an initial default value to the model's vectors.
   markupProcessData.colorRuns.Reserve(DEFAULT_VECTOR_SIZE);
@@ -856,6 +975,10 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
         ProcessTagForRun<ColorRun>(
           markupProcessData.backgroundColorRuns, styleStack, tag, characterIndex, backgroundRunIndex, backgroundTagReference, [](const Tag& tag, ColorRun& run) { ProcessBackground(tag, run); });
       }
+      else if(TokenComparison(XHTML_SPAN_TAG, tag.buffer, tag.length))
+      {
+        ProcessSpanForRun(tag, spanStack, markupProcessData.colorRuns, markupProcessData.fontRuns, colorRunIndex, fontRunIndex, characterIndex, spanTagReference);
+      }
     } // end if( IsTag() )
     else if(markupStringBuffer < markupStringEndBuffer)
     {