// 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-background.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>
#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
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 = '>';
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(),
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();
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;
};
/**
+ * @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.
}
/**
+ * @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 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.
}
/**
- * @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
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)
{
}
/**
+ * @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
* @param[in] fontRunIndex The font run index
* @param[in] colorRunIndex The color run index
+ * @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)
+void ResizeModelVectors(MarkupProcessData& markupProcessData, const RunIndex fontRunIndex, const RunIndex colorRunIndex, const RunIndex underlinedCharacterRunIndex, const RunIndex backgroundRunIndex)
{
markupProcessData.fontRuns.Resize(fontRunIndex);
markupProcessData.colorRuns.Resize(colorRunIndex);
+ markupProcessData.underlinedCharacterRuns.Resize(underlinedCharacterRunIndex);
+ markupProcessData.backgroundColorRuns.Resize(backgroundRunIndex);
#ifdef DEBUG_ENABLED
for(unsigned int i = 0; i < colorRunIndex; ++i)
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;
+ RunIndex colorRunIndex = 0u;
+ RunIndex fontRunIndex = 0u;
+ RunIndex underlinedCharacterRunIndex = 0u;
+ RunIndex backgroundRunIndex = 0u;
// check tag reference
- int colorTagReference = 0u;
- int fontTagReference = 0u;
- int iTagReference = 0u;
- int bTagReference = 0u;
+ int colorTagReference = 0u;
+ int fontTagReference = 0u;
+ int iTagReference = 0u;
+ 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);
markupProcessData.fontRuns.Reserve(DEFAULT_VECTOR_SIZE);
+ markupProcessData.underlinedCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE);
+ markupProcessData.backgroundColorRuns.Reserve(DEFAULT_VECTOR_SIZE);
// Get the mark-up string buffer.
const char* markupStringBuffer = markupString.c_str();
} // <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.
+ 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))
{
{
ProcessItemTag(markupProcessData, tag, characterIndex);
}
+ else if(TokenComparison(XHTML_BACKGROUND_TAG, tag.buffer, tag.length))
+ {
+ 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)
{
}
// Resize the model's vectors.
- ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex);
+ ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, backgroundRunIndex);
}
} // namespace Text