// 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-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/xhtml-entities.h>
-
-
namespace Dali
{
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 char LESS_THAN = '<';
const char GREATER_THAN = '>';
const char CHAR_ARRAY_END = '\0';
const char HEX_CODE = 'x';
-const char WHITE_SPACE = 0x20; // ASCII value of the white space.
+const char WHITE_SPACE = 0x20; // ASCII value of the white space.
// Range 1 0x0u < XHTML_DECIMAL_ENTITY_RANGE <= 0xD7FFu
// Range 2 0xE000u < XHTML_DECIMAL_ENTITY_RANGE <= 0xFFFDu
bool isQuotationOpen = false;
bool attributesFound = false;
tag.isEndTag = false;
+ bool isPreviousLessThan = false;
+ bool isPreviousSlash = false;
const char character = *markupStringBuffer;
if( LESS_THAN == character ) // '<'
{
tag.buffer = NULL;
tag.length = 0u;
+ isPreviousLessThan = true;
// if the iterator is pointing to a '<' character, then check if it's a mark-up tag is needed.
++markupStringBuffer;
{
const char character = *markupStringBuffer;
- if( SLASH == character ) // '/'
+ if( !isQuotationOpen && ( SLASH == character ) ) // '/'
{
- // if the tag has a '/' then it's an end or empty tag.
- tag.isEndTag = true;
+ if (isPreviousLessThan)
+ {
+ tag.isEndTag = true;
+ }
+ else
+ {
+ // if the tag has a '/' it may be an end tag.
+ isPreviousSlash = true;
+ }
- if( ( markupStringBuffer + 1u < markupStringEndBuffer ) && ( WHITE_SPACE >= *( markupStringBuffer + 1u ) ) && ( !isQuotationOpen ) )
+ isPreviousLessThan = false;
+ if( ( markupStringBuffer + 1u < markupStringEndBuffer ) && ( WHITE_SPACE >= *( markupStringBuffer + 1u ) ) )
{
++markupStringBuffer;
SkipWhiteSpace( markupStringBuffer, markupStringEndBuffer );
else if( GREATER_THAN == character ) // '>'
{
isTag = true;
+ if (isPreviousSlash)
+ {
+ tag.isEndTag = true;
+ }
+
+ isPreviousSlash = false;
+ isPreviousLessThan = false;
}
else if( QUOTATION_MARK == character )
{
isQuotationOpen = !isQuotationOpen;
++tag.length;
+
+ isPreviousSlash = false;
+ isPreviousLessThan = false;
}
else if( WHITE_SPACE >= character ) // ' '
{
// If it's not any of the 'special' characters then just add it to the tag string.
++tag.length;
+
+ isPreviousSlash = false;
+ isPreviousLessThan = false;
}
}
}
void ProcessMarkupString( const std::string& markupString, MarkupProcessData& markupProcessData )
{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "markupString: %s\n", markupString.c_str() );
+
// Reserve space for the plain text.
const Length markupStringSize = markupString.size();
markupProcessData.markupProcessedText.reserve( markupStringSize );
StyleStack::RunIndex colorRunIndex = 0u;
StyleStack::RunIndex fontRunIndex = 0u;
+ // check tag reference
+ int colorTagReference = 0u;
+ int fontTagReference = 0u;
+ int iTagReference = 0u;
+ int bTagReference = 0u;
+
// Give an initial default value to the model's vectors.
markupProcessData.colorRuns.Reserve( DEFAULT_VECTOR_SIZE );
markupProcessData.fontRuns.Reserve( DEFAULT_VECTOR_SIZE );
CharacterIndex characterIndex = 0u;
for( ; markupStringBuffer < markupStringEndBuffer; )
{
+ tag.attributes.Clear();
if( IsTag( markupStringBuffer,
markupStringEndBuffer,
tag ) )
// Point the next color run.
++colorRunIndex;
+
+ // Increase reference
+ ++colorTagReference;
}
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;
+ if( colorTagReference > 0 )
+ {
+ // 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;
+ --colorTagReference;
+ }
}
} // <color></color>
else if( TokenComparison( XHTML_I_TAG, tag.buffer, tag.length ) )
// Point the next free font run.
++fontRunIndex;
+
+ // Increase reference
+ ++iTagReference;
}
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;
+ if( iTagReference > 0 )
+ {
+ // 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;
+ --iTagReference;
+ }
}
} // <i></i>
else if( TokenComparison( XHTML_U_TAG, tag.buffer, tag.length ) )
// Point the next free font run.
++fontRunIndex;
+
+ // Increase reference
+ ++bTagReference;
}
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;
+ if( bTagReference > 0 )
+ {
+ // 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;
+ --bTagReference;
+ }
}
} // <b></b>
else if( TokenComparison( XHTML_FONT_TAG, tag.buffer, tag.length ) )
// Point the next free font run.
++fontRunIndex;
+
+ // Increase reference
+ ++fontTagReference;
}
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;
+ if( fontTagReference > 0 )
+ {
+ // 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;
+ --fontTagReference;
+ }
}
} // <font></font>
else if( TokenComparison( XHTML_SHADOW_TAG, tag.buffer, tag.length ) )
// Pop the top of the stack and set the number of characters of the run.
}
} // <outline></outline>
+ else if (TokenComparison(XHTML_ITEM_TAG, tag.buffer, tag.length))
+ {
+ if (tag.isEndTag)
+ {
+ // Create an embedded item instance.
+ EmbeddedItem item;
+ item.characterIndex = characterIndex;
+ ProcessEmbeddedItem(tag, item);
+
+ markupProcessData.items.PushBack(item);
+
+ // Insert white space character that will be replaced by the item.
+ markupProcessData.markupProcessedText.append( 1u, WHITE_SPACE );
+ ++characterIndex;
+ }
+ }
} // end if( IsTag() )
else if( markupStringBuffer < markupStringEndBuffer )
{
else
{
markupProcessData.colorRuns.Resize( colorRunIndex );
+
+#ifdef DEBUG_ENABLED
+ for( unsigned int i=0; i<colorRunIndex; ++i )
+ {
+ ColorRun& run = markupProcessData.colorRuns[i];
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "run[%d] index: %d, length: %d, color %f,%f,%f,%f\n", i, run.characterRun.characterIndex, run.characterRun.numberOfCharacters, run.color.r, run.color.g, run.color.b, run.color.a );
+ }
+#endif
}
}