Merge "Removed 3D layer dependency of Model3dView and Mesh Visual." into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / markup-processor.cpp
index 84707ad..6ea6352 100644 (file)
@@ -20,6 +20,8 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/markup-processor-color.h>
+#include <dali-toolkit/internal/text/markup-processor-font.h>
 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
 
 namespace Dali
@@ -45,18 +47,81 @@ const std::string XHTML_SHADOW_TAG("shadow");
 const std::string XHTML_GLOW_TAG("glow");
 const std::string XHTML_OUTLINE_TAG("outline");
 
-const char LESS_THAN         = '<';
-const char GREATER_THAN      = '>';
-const char EQUAL             = '=';
-const char QUOTATION_MARK    = '\'';
-const char LINE_SEPARATOR_CR = 0x0D; // Carriage return character  CR
-const char LINE_SEPARATOR_LF = 0x0A; // New line character         LF
-const char SLASH             = '/';
-const char BACK_SLASH        = '\\';
+const char LESS_THAN      = '<';
+const char GREATER_THAN   = '>';
+const char EQUAL          = '=';
+const char QUOTATION_MARK = '\'';
+const char SLASH          = '/';
+const char BACK_SLASH     = '\\';
 
-const char WHITE_SPACE       = 0x20; // ASCII value of the white space.
+const char WHITE_SPACE    = 0x20; // ASCII value of the white space.
 
 const unsigned int MAX_NUM_OF_ATTRIBUTES =  5u; ///< The font tag has the 'family', 'size' 'weight', 'width' and 'slant' attrubutes.
+const unsigned int DEFAULT_VECTOR_SIZE   = 16u; ///< Default size of run vectors.
+
+/**
+ * @brief Struct used to retrieve the style runs from the mark-up string.
+ */
+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.
+
+  StyleStack()
+  : stack(),
+    topIndex( 0u )
+  {
+    stack.Resize( DEFAULT_VECTOR_SIZE );
+  }
+
+  void Push( RunIndex index )
+  {
+    // Check if there is space inside the style stack.
+    const VectorBase::SizeType size = stack.Count();
+    if( topIndex >= size )
+    {
+      // Resize the style stack.
+      stack.Resize( 2u * size );
+    }
+
+    // Set the run index in the top of the stack.
+    *( stack.Begin() + topIndex ) = index;
+
+    // Reposition the pointer to the top of the stack.
+    ++topIndex;
+  }
+
+  RunIndex Pop()
+  {
+    // Pop the top of the stack.
+    --topIndex;
+    return *( stack.Begin() + topIndex );
+  }
+};
+
+/**
+ * @brief Initializes a font run description to its defaults.
+ *
+ * @param[in,out] fontRun The font description run to initialize.
+ */
+void Initialize( FontDescriptionRun& fontRun )
+{
+  fontRun.characterRun.characterIndex = 0u;
+  fontRun.characterRun.numberOfCharacters = 0u;
+  fontRun.familyName = NULL;
+  fontRun.familyLength = 0u;
+  fontRun.weight = TextAbstraction::FontWeight::NORMAL;
+  fontRun.width = TextAbstraction::FontWidth::NORMAL;
+  fontRun.slant = TextAbstraction::FontSlant::NORMAL;
+  fontRun.size = 0u;
+  fontRun.familyDefined = false;
+  fontRun.weightDefined = false;
+  fontRun.widthDefined = false;
+  fontRun.slantDefined = false;
+  fontRun.sizeDefined = false;
+}
 
 /**
  * @brief Splits the tag string into the tag name and its attributes.
@@ -297,6 +362,17 @@ void ProcessMarkupString( const std::string& markupString, MarkupProcessData& ma
   const Length markupStringSize = markupString.size();
   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;
+
+  // Points the next free position in the vector of runs.
+  StyleStack::RunIndex colorRunIndex = 0u;
+  StyleStack::RunIndex fontRunIndex = 0u;
+
+  // Give an initial default value to the model's vectors.
+  markupProcessData.colorRuns.Reserve( DEFAULT_VECTOR_SIZE );
+  markupProcessData.fontRuns.Reserve( DEFAULT_VECTOR_SIZE );
+
   // Get the mark-up string buffer.
   const char* markupStringBuffer = markupString.c_str();
   const char* const markupStringEndBuffer = markupStringBuffer + markupStringSize;
@@ -314,10 +390,29 @@ void ProcessMarkupString( const std::string& markupString, MarkupProcessData& ma
         if( !tag.isEndTag )
         {
           // Create a new color run.
+          ColorRun colorRun;
+          colorRun.characterRun.numberOfCharacters = 0u;
+
+          // Set the start character index.
+          colorRun.characterRun.characterIndex = characterIndex;
+
+          // Fill the run with the attributes.
+          ProcessColorTag( tag, colorRun );
+
+          // Push the color run in the logical model.
+          markupProcessData.colorRuns.PushBack( colorRun );
+
+          // Push the index of the run into the stack.
+          styleStack.Push( colorRunIndex );
+
+          // Point the next color run.
+          ++colorRunIndex;
         }
         else
         {
           // Pop the top of the stack and set the number of characters of the run.
+          ColorRun& colorRun = *( markupProcessData.colorRuns.Begin() + styleStack.Pop() );
+          colorRun.characterRun.numberOfCharacters = characterIndex - colorRun.characterRun.characterIndex;
         }
       } // <color></color>
       else if( TokenComparison( XHTML_I_TAG, tag.buffer, tag.length ) )
@@ -325,10 +420,28 @@ void ProcessMarkupString( const std::string& markupString, MarkupProcessData& ma
         if( !tag.isEndTag )
         {
           // Create a new font run.
+          FontDescriptionRun fontRun;
+          Initialize( fontRun );
+
+          // Fill the run with the parameters.
+          fontRun.characterRun.characterIndex = characterIndex;
+          fontRun.slant = TextAbstraction::FontSlant::ITALIC;
+          fontRun.slantDefined = true;
+
+          // Push the font run in the logical model.
+          markupProcessData.fontRuns.PushBack( fontRun );
+
+          // Push the index of the run into the stack.
+          styleStack.Push( fontRunIndex );
+
+          // Point the next free font run.
+          ++fontRunIndex;
         }
         else
         {
           // Pop the top of the stack and set the number of characters of the run.
+          FontDescriptionRun& fontRun = *( markupProcessData.fontRuns.Begin() + styleStack.Pop() );
+          fontRun.characterRun.numberOfCharacters = characterIndex - fontRun.characterRun.characterIndex;
         }
       } // <i></i>
       else if( TokenComparison( XHTML_U_TAG, tag.buffer, tag.length ) )
@@ -347,10 +460,28 @@ void ProcessMarkupString( const std::string& markupString, MarkupProcessData& ma
         if( !tag.isEndTag )
         {
           // Create a new font run.
+          FontDescriptionRun fontRun;
+          Initialize( fontRun );
+
+          // Fill the run with the parameters.
+          fontRun.characterRun.characterIndex = characterIndex;
+          fontRun.weight = TextAbstraction::FontWeight::BOLD;
+          fontRun.weightDefined = true;
+
+          // Push the font run in the logical model.
+          markupProcessData.fontRuns.PushBack( fontRun );
+
+          // Push the index of the run into the stack.
+          styleStack.Push( fontRunIndex );
+
+          // Point the next free font run.
+          ++fontRunIndex;
         }
         else
         {
           // Pop the top of the stack and set the number of characters of the run.
+          FontDescriptionRun& fontRun = *( markupProcessData.fontRuns.Begin() + styleStack.Pop() );
+          fontRun.characterRun.numberOfCharacters = characterIndex - fontRun.characterRun.characterIndex;
         }
       } // <b></b>
       else if( TokenComparison( XHTML_FONT_TAG, tag.buffer, tag.length ) )
@@ -358,10 +489,28 @@ void ProcessMarkupString( const std::string& markupString, MarkupProcessData& ma
         if( !tag.isEndTag )
         {
           // Create a new font run.
+          FontDescriptionRun fontRun;
+          Initialize( fontRun );
+
+          // Fill the run with the parameters.
+          fontRun.characterRun.characterIndex = characterIndex;
+
+          ProcessFontTag( tag, fontRun );
+
+          // Push the font run in the logical model.
+          markupProcessData.fontRuns.PushBack( fontRun );
+
+          // Push the index of the run into the stack.
+          styleStack.Push( fontRunIndex );
+
+          // Point the next free font run.
+          ++fontRunIndex;
         }
         else
         {
           // Pop the top of the stack and set the number of characters of the run.
+          FontDescriptionRun& fontRun = *( markupProcessData.fontRuns.Begin() + styleStack.Pop() );
+          fontRun.characterRun.numberOfCharacters = characterIndex - fontRun.characterRun.characterIndex;
         }
       } // <font></font>
       else if( TokenComparison( XHTML_SHADOW_TAG, tag.buffer, tag.length ) )
@@ -412,15 +561,6 @@ void ProcessMarkupString( const std::string& markupString, MarkupProcessData& ma
           ++markupStringBuffer;
         }
       }
-      else if( ( LINE_SEPARATOR_CR == character ) && ( markupStringBuffer + 1u < markupStringEndBuffer ) )
-      {
-        // Replacing CR+LF end line by LF.
-        if( LINE_SEPARATOR_LF == *( markupStringBuffer + 1u ) )
-        {
-          character = LINE_SEPARATOR_LF;
-          ++markupStringBuffer;
-        }
-      }
 
       const unsigned char numberOfBytes = GetUtf8Length( character );
 
@@ -437,6 +577,23 @@ void ProcessMarkupString( const std::string& markupString, MarkupProcessData& ma
   }
 
   // Resize the model's vectors.
+  if( 0u == fontRunIndex )
+  {
+    markupProcessData.fontRuns.Clear();
+  }
+  else
+  {
+    markupProcessData.fontRuns.Resize( fontRunIndex );
+  }
+
+  if( 0u == colorRunIndex )
+  {
+    markupProcessData.colorRuns.Clear();
+  }
+  else
+  {
+    markupProcessData.colorRuns.Resize( colorRunIndex );
+  }
 }
 
 } // namespace Text