Merge branch 'devel/master' into devel/graphics
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / markup-processor.cpp
index 20a5825..ea7f869 100644 (file)
@@ -25,6 +25,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/markup-processor-anchor.h>
 #include <dali-toolkit/internal/text/markup-processor-color.h>
 #include <dali-toolkit/internal/text/markup-processor-embedded-item.h>
 #include <dali-toolkit/internal/text/markup-processor-font.h>
@@ -51,6 +52,7 @@ const std::string XHTML_SHADOW_TAG("shadow");
 const std::string XHTML_GLOW_TAG("glow");
 const std::string XHTML_OUTLINE_TAG("outline");
 const std::string XHTML_ITEM_TAG("item");
+const std::string XHTML_ANCHOR_TAG("a");
 
 const char LESS_THAN      = '<';
 const char GREATER_THAN   = '>';
@@ -154,6 +156,17 @@ void Initialize(ColorRun& colorRun)
 }
 
 /**
+ * @brief Initializes a underlined character run to its defaults.
+ *
+ * @param[in,out] underlinedCharacterRun The underelined character run to initialize.
+ */
+void Initialize(UnderlinedCharacterRun& underlinedCharacterRun)
+{
+  underlinedCharacterRun.characterRun.characterIndex     = 0u;
+  underlinedCharacterRun.characterRun.numberOfCharacters = 0u;
+}
+
+/**
  * @brief Splits the tag string into the tag name and its attributes.
  *
  * The attributes are stored in a vector in the tag.
@@ -496,9 +509,9 @@ bool XHTMLNumericEntityToUtf8(const char* markupText, char* utf8)
 }
 
 /**
- * @brief Processes a particular tag for the required run (color-run or font-run).
+ * @brief Processes a particular tag for the required run (color-run, font-run or underlined-character-run).
  *
- * @tparam RunType Whether ColorRun or FontDescriptionRun
+ * @tparam RunType Whether ColorRun , FontDescriptionRun or UnderlinedCharacterRun
  *
  * @param[in/out] runsContainer The container containing all the runs
  * @param[in/out] styleStack The style stack
@@ -580,16 +593,50 @@ void ProcessItemTag(
 }
 
 /**
+ * @brief Processes the anchor tag
+ *
+ * @param[in/out] markupProcessData The markup process data
+ * @param[in] tag The current tag
+ * @param[in/out] characterIndex The current character index
+ */
+void ProcessAnchorTag(
+  MarkupProcessData& markupProcessData,
+  const Tag          tag,
+  CharacterIndex&    characterIndex)
+{
+  if(!tag.isEndTag)
+  {
+    // Create an anchor instance.
+    Anchor anchor;
+    anchor.startIndex = characterIndex;
+    anchor.endIndex   = 0u;
+    ProcessAnchor(tag, anchor);
+    markupProcessData.anchors.PushBack(anchor);
+  }
+  else
+  {
+    // Update end index.
+    unsigned int count = markupProcessData.anchors.Count();
+    if(count > 0)
+    {
+      markupProcessData.anchors[count - 1].endIndex = characterIndex;
+    }
+  }
+}
+
+/**
  * @brief Resizes the model's vectors
  *
  * @param[in/out] markupProcessData The markup process data
  * @param[in] fontRunIndex The font run index
  * @param[in] colorRunIndex The color run index
+ * @param[in] underlinedCharacterRunIndex The underlined character run index
  */
-void ResizeModelVectors(MarkupProcessData& markupProcessData, const StyleStack::RunIndex fontRunIndex, const StyleStack::RunIndex colorRunIndex)
+void ResizeModelVectors(MarkupProcessData& markupProcessData, const StyleStack::RunIndex fontRunIndex, const StyleStack::RunIndex colorRunIndex, const StyleStack::RunIndex underlinedCharacterRunIndex)
 {
   markupProcessData.fontRuns.Resize(fontRunIndex);
   markupProcessData.colorRuns.Resize(colorRunIndex);
+  markupProcessData.underlinedCharacterRuns.Resize(underlinedCharacterRunIndex);
 
 #ifdef DEBUG_ENABLED
   for(unsigned int i = 0; i < colorRunIndex; ++i)
@@ -706,18 +753,21 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
   StyleStack styleStack;
 
   // Points the next free position in the vector of runs.
-  StyleStack::RunIndex colorRunIndex = 0u;
-  StyleStack::RunIndex fontRunIndex  = 0u;
+  StyleStack::RunIndex colorRunIndex                = 0u;
+  StyleStack::RunIndex fontRunIndex                 = 0u;
+  StyleStack::RunIndex underlinedCharacterRunIndex  = 0u;
 
   // check tag reference
   int colorTagReference = 0u;
   int fontTagReference  = 0u;
   int iTagReference     = 0u;
   int bTagReference     = 0u;
+  int uTagReference     = 0u;
 
   // Give an initial default value to the model's vectors.
   markupProcessData.colorRuns.Reserve(DEFAULT_VECTOR_SIZE);
   markupProcessData.fontRuns.Reserve(DEFAULT_VECTOR_SIZE);
+  markupProcessData.underlinedCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE);
 
   // Get the mark-up string buffer.
   const char*       markupStringBuffer    = markupString.c_str();
@@ -747,9 +797,9 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
       } // <i></i>
       else if(TokenComparison(XHTML_U_TAG, tag.buffer, tag.length))
       {
-        // TODO: If !tag.isEndTag, then create a new underline run.
-        //       else Pop the top of the stack and set the number of characters of the run.
-      } // <u></u>
+        ProcessTagForRun<UnderlinedCharacterRun>(
+          markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) {  });
+      }  // <u></u>
       else if(TokenComparison(XHTML_B_TAG, tag.buffer, tag.length))
       {
         ProcessTagForRun<FontDescriptionRun>(
@@ -763,6 +813,18 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
         ProcessTagForRun<FontDescriptionRun>(
           markupProcessData.fontRuns, styleStack, tag, characterIndex, fontRunIndex, fontTagReference, [](const Tag& tag, FontDescriptionRun& fontRun) { ProcessFontTag(tag, fontRun); });
       } // <font></font>
+      else if(TokenComparison(XHTML_ANCHOR_TAG, tag.buffer, tag.length))
+      {
+        /* Anchor */
+        ProcessAnchorTag(markupProcessData, tag, characterIndex);
+        /* Color */
+        ProcessTagForRun<ColorRun>(
+          markupProcessData.colorRuns, styleStack, tag, characterIndex, colorRunIndex, colorTagReference, [](const Tag& tag, ColorRun& run) {
+            run.color = Color::BLUE;
+            ProcessColorTag(tag, run);
+          });
+        /* TODO - underline */
+      } // <a href=https://www.tizen.org>tizen</a>
       else if(TokenComparison(XHTML_SHADOW_TAG, tag.buffer, tag.length))
       {
         // TODO: If !tag.isEndTag, then create a new shadow run.
@@ -790,7 +852,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
   }
 
   // Resize the model's vectors.
-  ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex);
+  ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex);
 }
 
 } // namespace Text