The inner tag inherit the attributes of the outer tag and override them when defined in the inner tag
Example:
"<s height='5.0f' color='blue'> outer tag before <s color='green'> inner tag </s> outer tag after </s>"
"outer tag before" and "outer tag after" have height = 5.0f and color = 'blue'
"inner tag" has height = 5.0f and color = 'green'
This patch should be preceded by the patch below:
https://review.tizen.org/gerrit/c/platform/core/uifw/dali-toolkit/+/272264
Change-Id: I7426507b14c73f09aca67b9a22173e8ee5c0db29
END_TEST;
}
+int UtcDaliTextEditorMarkupNestedStrikethroughTags(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextEditorMarkupNestedStrikethroughTags ");
+
+ TextEditor textEditor = TextEditor::New();
+
+ application.GetScene().Add(textEditor);
+
+ std::string testText = "start<s height='5.0f' color='green' >AB<s color='blue' >XYZ</s>CDE</s>end";
+
+ textEditor.SetProperty(TextEditor::Property::TEXT, testText);
+ textEditor.SetProperty(TextEditor ::Property::ENABLE_MARKUP, true);
+
+ application.SendNotification();
+ application.Render();
+
+ const uint32_t expectedNumberOfStrikethroughRuns = 2u;
+
+ Toolkit::Internal::TextEditor& textEditorImpl = GetImpl(textEditor);
+ const Text::Length numberOfStrikethroughRuns = textEditorImpl.GetTextController()->GetTextModel()->GetNumberOfStrikethroughRuns();
+
+ DALI_TEST_EQUALS(numberOfStrikethroughRuns, expectedNumberOfStrikethroughRuns, TEST_LOCATION);
+
+ Vector<StrikethroughGlyphRun> strikethroughRuns;
+ strikethroughRuns.Resize(numberOfStrikethroughRuns);
+ textEditorImpl.GetTextController()->GetTextModel()->GetStrikethroughRuns(strikethroughRuns.Begin(), 0u, numberOfStrikethroughRuns);
+
+ struct DataOfCase
+ {
+ std::string title;
+ GlyphIndex glyphIndex;
+ Length numberOfGlyphs;
+ StrikethroughStyleProperties properties;
+ };
+ DataOfCase data[] =
+ {
+ //Outter
+ {"<s height='5.0f' color='green' >AB<s color='blue' >XYZ</s>CDE</s>",
+ 5u,
+ 8u,
+ {
+ Color::GREEN,
+ 5.0f,
+ true,
+ true,
+ }},
+
+ //Inner
+ {"<s color='blue' >XYZ</s>",
+ 7u,
+ 3u,
+ {
+ Color::BLUE,
+ 5.0f,
+ true,
+ true,
+ }},
+
+ };
+
+ for(uint32_t i = 0; i < expectedNumberOfStrikethroughRuns; i++)
+ {
+ tet_infoline(data[i].title.c_str());
+ DALI_TEST_EQUALS(strikethroughRuns[i].glyphRun.glyphIndex, data[i].glyphIndex, TEST_LOCATION);
+ DALI_TEST_EQUALS(strikethroughRuns[i].glyphRun.numberOfGlyphs, data[i].numberOfGlyphs, TEST_LOCATION);
+ DALI_TEST_CHECK(data[i].properties == strikethroughRuns[i].properties);
+ }
+
+ END_TEST;
+}
+
int UtcDaliTextEditorMarkupStrikethroughAttributes(void)
{
ToolkitTestApplication application;
END_TEST;
}
+int UtcDaliTextFieldMarkupNestedStrikethroughTags(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextFieldMarkupNestedStrikethroughTags ");
+
+ TextField textField = TextField::New();
+
+ application.GetScene().Add(textField);
+
+ std::string testText = "start<s height='5.0f' color='green' >AB<s color='blue' >XYZ</s>CDE</s>end";
+
+ textField.SetProperty(TextField::Property::TEXT, testText);
+ textField.SetProperty(TextField ::Property::ENABLE_MARKUP, true);
+
+ application.SendNotification();
+ application.Render();
+
+ const uint32_t expectedNumberOfStrikethroughRuns = 2u;
+
+ Toolkit::Internal::TextField& textFieldImpl = GetImpl(textField);
+ const Text::Length numberOfStrikethroughRuns = textFieldImpl.GetTextController()->GetTextModel()->GetNumberOfStrikethroughRuns();
+
+ DALI_TEST_EQUALS(numberOfStrikethroughRuns, expectedNumberOfStrikethroughRuns, TEST_LOCATION);
+
+ Vector<StrikethroughGlyphRun> strikethroughRuns;
+ strikethroughRuns.Resize(numberOfStrikethroughRuns);
+ textFieldImpl.GetTextController()->GetTextModel()->GetStrikethroughRuns(strikethroughRuns.Begin(), 0u, numberOfStrikethroughRuns);
+
+ struct DataOfCase
+ {
+ std::string title;
+ GlyphIndex glyphIndex;
+ Length numberOfGlyphs;
+ StrikethroughStyleProperties properties;
+ };
+ DataOfCase data[] =
+ {
+ //Outter
+ {"<s height='5.0f' color='green' >AB<s color='blue' >XYZ</s>CDE</s>",
+ 5u,
+ 8u,
+ {
+ Color::GREEN,
+ 5.0f,
+ true,
+ true,
+ }},
+
+ //Inner
+ {"<s color='blue' >XYZ</s>",
+ 7u,
+ 3u,
+ {
+ Color::BLUE,
+ 5.0f,
+ true,
+ true,
+ }},
+
+ };
+
+ for(uint32_t i = 0; i < expectedNumberOfStrikethroughRuns; i++)
+ {
+ tet_infoline(data[i].title.c_str());
+ DALI_TEST_EQUALS(strikethroughRuns[i].glyphRun.glyphIndex, data[i].glyphIndex, TEST_LOCATION);
+ DALI_TEST_EQUALS(strikethroughRuns[i].glyphRun.numberOfGlyphs, data[i].numberOfGlyphs, TEST_LOCATION);
+ DALI_TEST_CHECK(data[i].properties == strikethroughRuns[i].properties);
+ }
+
+ END_TEST;
+}
+
int UtcDaliTextFieldMarkupStrikethroughAttributes(void)
{
ToolkitTestApplication application;
END_TEST;
}
+int UtcDaliTextLabelMarkupNestedStrikethroughTags(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextLabelMarkupNestedStrikethroughTags ");
+
+ TextLabel textLabel = TextLabel::New();
+
+ application.GetScene().Add(textLabel);
+
+ std::string testText = "start<s height='5.0f' color='green' >AB<s color='blue' >XYZ</s>CDE</s>end";
+
+ textLabel.SetProperty(TextLabel::Property::TEXT, testText);
+ textLabel.SetProperty(TextLabel ::Property::ENABLE_MARKUP, true);
+
+ application.SendNotification();
+ application.Render();
+
+ const uint32_t expectedNumberOfStrikethroughRuns = 2u;
+
+ Toolkit::Internal::TextLabel& textLabelImpl = GetImpl(textLabel);
+ const Text::Length numberOfStrikethroughRuns = textLabelImpl.GetTextController()->GetTextModel()->GetNumberOfStrikethroughRuns();
+
+ DALI_TEST_EQUALS(numberOfStrikethroughRuns, expectedNumberOfStrikethroughRuns, TEST_LOCATION);
+
+ Vector<StrikethroughGlyphRun> strikethroughRuns;
+ strikethroughRuns.Resize(numberOfStrikethroughRuns);
+ textLabelImpl.GetTextController()->GetTextModel()->GetStrikethroughRuns(strikethroughRuns.Begin(), 0u, numberOfStrikethroughRuns);
+
+ struct DataOfCase
+ {
+ std::string title;
+ GlyphIndex glyphIndex;
+ Length numberOfGlyphs;
+ StrikethroughStyleProperties properties;
+ };
+ DataOfCase data[] =
+ {
+ //Outter
+ {"<s height='5.0f' color='green' >AB<s color='blue' >XYZ</s>CDE</s>",
+ 5u,
+ 8u,
+ {
+ Color::GREEN,
+ 5.0f,
+ true,
+ true,
+ }},
+
+ //Inner
+ {"<s color='blue' >XYZ</s>",
+ 7u,
+ 3u,
+ {
+ Color::BLUE,
+ 5.0f,
+ true,
+ true,
+ }},
+
+ };
+
+ for(uint32_t i = 0; i < expectedNumberOfStrikethroughRuns; i++)
+ {
+ tet_infoline(data[i].title.c_str());
+ DALI_TEST_EQUALS(strikethroughRuns[i].glyphRun.glyphIndex, data[i].glyphIndex, TEST_LOCATION);
+ DALI_TEST_EQUALS(strikethroughRuns[i].glyphRun.numberOfGlyphs, data[i].numberOfGlyphs, TEST_LOCATION);
+ DALI_TEST_CHECK(data[i].properties == strikethroughRuns[i].properties);
+ }
+
+ END_TEST;
+}
+
int UtcDaliTextLabelMarkupStrikethroughAttributes(void)
{
ToolkitTestApplication application;
}
}
+void OverrideNestedStrikethroughCharacterRuns(Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns)
+{
+ // Handle nested tags
+ // The inner tag inherit the attributes of the outer tag and override them when defined in the inner tag.
+ // Example:
+ // <s height='5.0f' color='blue'> outer tag before <s color='green'> inner tag </s> outer tag after </s>
+ // "outer tag before" and "outer tag after" have height = 5.0f and color = 'blue'
+ // "inner tag" has height = 5.0f and color = 'green'
+
+ if(strikethroughCharacterRuns.Count() > 0u)
+ {
+ Vector<StrikethroughCharacterRun>::ConstIterator preIt = strikethroughCharacterRuns.Begin();
+
+ Vector<StrikethroughCharacterRun>::Iterator it = strikethroughCharacterRuns.Begin() + 1;
+ Vector<StrikethroughCharacterRun>::ConstIterator endIt = strikethroughCharacterRuns.End();
+
+ while(it != endIt)
+ {
+ const StrikethroughCharacterRun& run = *it;
+ const CharacterIndex& characterIndex = run.characterRun.characterIndex;
+ const Length& numberOfCharacters = run.characterRun.numberOfCharacters;
+
+ const StrikethroughCharacterRun& preRun = *preIt;
+ const CharacterIndex& preCharacterIndex = preRun.characterRun.characterIndex;
+ const Length& preNumberOfCharacters = preRun.characterRun.numberOfCharacters;
+
+ if((preCharacterIndex <= characterIndex) &&
+ ((characterIndex + numberOfCharacters) <= (preCharacterIndex + preNumberOfCharacters)))
+ {
+ it->properties.CopyIfNotDefined(preIt->properties);
+ }
+
+ it++;
+ preIt++;
+ }
+ }
+}
+
} // namespace Text
} // namespace Toolkit
*
*/
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/strikethrough-character-run.h>
+
namespace Dali
{
namespace Toolkit
*/
void ProcessStrikethroughTag(const Tag& tag, StrikethroughCharacterRun& strikethroughRun);
+/**
+ * @brief Override the run's attributes which contained in the previous run. This is to handle the nested tags.
+ *
+ * @param[in,out] strikethroughCharacterRun The list of strikethrough character run
+ */
+void OverrideNestedStrikethroughCharacterRuns(Vector<StrikethroughCharacterRun>& strikethroughCharacterRun);
+
} // namespace Text
} // namespace Toolkit
// Handle the nested tags
OverrideNestedUnderlinedCharacterRuns(markupProcessData.underlinedCharacterRuns);
+ OverrideNestedStrikethroughCharacterRuns(markupProcessData.strikethroughCharacterRuns);
}
} // namespace Text
Vector<StrikethroughGlyphRun>::ConstIterator currentStrikethroughGlyphRunIt = strikethroughRuns.End();
const bool isGlyphStrikethrough = strikethroughEnabled || IsGlyphStrikethrough(i, strikethroughRuns, currentStrikethroughGlyphRunIt);
- const StrikethroughStyleProperties currentStrikethroughProperties = GetCurrentStrikethroughProperties(isGlyphStrikethrough, strikethroughRuns, currentStrikethroughGlyphRunIt, viewStrikethroughProperties);
- float currentStrikethroughHeight = GetCurrentStrikethroughHeight(strikethroughRuns, currentStrikethroughGlyphRunIt, viewStrikethroughProperties.height);
+ const StrikethroughStyleProperties currentStrikethroughProperties = GetCurrentStrikethroughProperties(i, isGlyphStrikethrough, strikethroughRuns, currentStrikethroughGlyphRunIt, viewStrikethroughProperties);
+ float currentStrikethroughHeight = currentStrikethroughProperties.height;
thereAreStrikethroughGlyphs = thereAreStrikethroughGlyphs || isGlyphStrikethrough;
// No operation for white space
return false;
}
-float GetCurrentStrikethroughHeight(const Vector<StrikethroughGlyphRun>& strikethroughRuns,
- Vector<StrikethroughGlyphRun>::ConstIterator currentStrikethroughGlyphRunIt,
- const float strikethroughHeight)
+StrikethroughStyleProperties GetCurrentStrikethroughProperties(GlyphIndex index,
+ const bool& isGlyphStrikethrough,
+ const Vector<StrikethroughGlyphRun>& strikethroughRuns,
+ Vector<StrikethroughGlyphRun>::ConstIterator& currentStrikethroughGlyphRunIt,
+ const StrikethroughStyleProperties& commonStrikethroughProperties)
{
- if(currentStrikethroughGlyphRunIt == strikethroughRuns.End())
+ StrikethroughStyleProperties currentStrikethroughStyleProperties = commonStrikethroughProperties;
+
+ if(isGlyphStrikethrough && (currentStrikethroughGlyphRunIt != strikethroughRuns.End()))
{
- return strikethroughHeight;
- }
+ // Retrieve the latest run to handle the nested case.
+ for(Vector<StrikethroughGlyphRun>::ConstIterator it = currentStrikethroughGlyphRunIt + 1,
+ endIt = strikethroughRuns.End();
+ it != endIt;
+ ++it)
+ {
+ const StrikethroughGlyphRun& run = *it;
- const StrikethroughGlyphRun& strikethroughGlyphRun = *currentStrikethroughGlyphRunIt;
- return (strikethroughGlyphRun.properties.heightDefined ? strikethroughGlyphRun.properties.height : strikethroughHeight);
-}
+ if((run.glyphRun.glyphIndex <= index) && (index < (run.glyphRun.glyphIndex + run.glyphRun.numberOfGlyphs)))
+ {
+ currentStrikethroughGlyphRunIt = it;
+ }
+ }
-StrikethroughStyleProperties GetCurrentStrikethroughProperties(const bool& isGlyphStrikethrough,
- const Vector<StrikethroughGlyphRun>& strikethroughRuns,
- Vector<StrikethroughGlyphRun>::ConstIterator currentStrikethroughGlyphRunIt,
- const StrikethroughStyleProperties& commonStrikethroughProperties)
-{
- return (isGlyphStrikethrough && (currentStrikethroughGlyphRunIt != strikethroughRuns.End()))
- ? currentStrikethroughGlyphRunIt->properties
- : commonStrikethroughProperties;
+ currentStrikethroughStyleProperties.OverrideByDefinedProperties(currentStrikethroughGlyphRunIt->properties);
+ }
+
+ return currentStrikethroughStyleProperties;
}
/// Helper method to fetch the strikethrough metrics for the specified font glyph
Vector<StrikethroughGlyphRun>::ConstIterator& currentStrikethroughGlyphRunIt);
/**
- * @brief Check the current strikethrough glyph run iterator if not empty and its height is defined then return ts height. Otherwise return the common strikethrough height.
- *
- * @param[in] strikethroughRuns the strikethrough runs.
- * @param[in] currentStrikethroughGlyphRunIt the iterator of current strikethrough glyph run.
- * @param[in] strikethroughHeight the common strikethrough height.
- *
- * @return the determined strikethrough height
- */
-float GetCurrentStrikethroughHeight(const Vector<StrikethroughGlyphRun>& strikethroughRuns,
- Vector<StrikethroughGlyphRun>::ConstIterator currentStrikethroughGlyphRunIt,
- const float strikethroughHeight);
-
-/**
* @brief Check the current strikethrough glyph run iterator if not empty and isGlyphStrikethrough is true then return its StrikethroughProperties. Otherwise return the common strikethrough properties.
*
+ * @param[in] index the index of glyph.
* @param[in] isGlyphStrikethrough whether the glyph is strikethrough.
* @param[in] strikethroughRuns the strikethrough runs.
* @param[in] currentStrikethroughGlyphRunIt the iterator of current strikethrough glyph run.
*
* @return the determined strikethrough properties
*/
-StrikethroughStyleProperties GetCurrentStrikethroughProperties(const bool& isGlyphStrikethrough,
- const Vector<StrikethroughGlyphRun>& strikethroughRuns,
- Vector<StrikethroughGlyphRun>::ConstIterator currentStrikethroughGlyphRunIt,
- const StrikethroughStyleProperties& commonStrikethroughProperties);
+StrikethroughStyleProperties GetCurrentStrikethroughProperties(GlyphIndex index,
+ const bool& isGlyphStrikethrough,
+ const Vector<StrikethroughGlyphRun>& strikethroughRuns,
+ Vector<StrikethroughGlyphRun>::ConstIterator& currentStrikethroughGlyphRunIt,
+ const StrikethroughStyleProperties& commonStrikethroughProperties);
/**
* @brief Calculate the current strikethrough height and update maximum strikethrough height
Vector<StrikethroughGlyphRun>::ConstIterator currentStrikethroughGlyphRunIt = strikethroughRuns.End();
const bool strikethroughGlyph = strikethroughEnabled || IsGlyphStrikethrough(glyphIndex, strikethroughRuns, currentStrikethroughGlyphRunIt);
- currentStrikethroughProperties = GetCurrentStrikethroughProperties(strikethroughGlyph, strikethroughRuns, currentStrikethroughGlyphRunIt, modelStrikethroughProperties);
- currentStrikethroughHeight = GetCurrentStrikethroughHeight(strikethroughRuns, currentStrikethroughGlyphRunIt, modelStrikethroughProperties.height);
+ currentStrikethroughProperties = GetCurrentStrikethroughProperties(glyphIndex, strikethroughGlyph, strikethroughRuns, currentStrikethroughGlyphRunIt, modelStrikethroughProperties);
+ currentStrikethroughHeight = currentStrikethroughProperties.height;
thereAreStrikethroughGlyphs = thereAreStrikethroughGlyphs || strikethroughGlyph;
// Are we still using the same fontId as previous
return ((!heightDefined && !other.heightDefined) || ((heightDefined && other.heightDefined) && (height == other.height)));
}
+ StrikethroughStyleProperties& CopyIfNotDefined(const StrikethroughStyleProperties& other)
+ {
+ //Copy only the defined properties in other and not defined in this from other to this
+
+ if(!heightDefined && other.heightDefined)
+ {
+ height = other.height;
+ heightDefined = true;
+ }
+
+ if(!colorDefined && other.colorDefined)
+ {
+ color = other.color;
+ colorDefined = true;
+ }
+
+ // to chain this method
+ return *this;
+ }
+
+ StrikethroughStyleProperties& OverrideByDefinedProperties(const StrikethroughStyleProperties& other)
+ {
+ //Copy only the defined properties in other from other to this
+
+ if(other.heightDefined)
+ {
+ height = other.height;
+ heightDefined = true;
+ }
+
+ if(other.colorDefined)
+ {
+ color = other.color;
+ colorDefined = true;
+ }
+
+ // to chain this method
+ return *this;
+ }
+
//Attributes
Vector4 color; ///< The color of strikethrough.
float height; ///< The height of strikethrough.