From: ssabah Date: Mon, 14 Mar 2022 12:05:12 +0000 (+0300) Subject: Handled nested tags in strikethrough X-Git-Tag: dali_2.1.15~1 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=e770d32b7703435f37ec18ceadf76df623355c24 Handled nested tags in strikethrough The inner tag inherit the attributes of the outer tag and override them when defined in the inner tag Example: " outer tag before inner tag outer tag after " "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 --- diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp index ade6b11..d19326f 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp @@ -600,6 +600,78 @@ int UtcDaliTextEditorMarkupNestedUnderlineTags(void) END_TEST; } +int UtcDaliTextEditorMarkupNestedStrikethroughTags(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorMarkupNestedStrikethroughTags "); + + TextEditor textEditor = TextEditor::New(); + + application.GetScene().Add(textEditor); + + std::string testText = "startABXYZCDEend"; + + 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 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 + {"ABXYZCDE", + 5u, + 8u, + { + Color::GREEN, + 5.0f, + true, + true, + }}, + + //Inner + {"XYZ", + 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; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp index da74a7a..02aa540 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp @@ -684,6 +684,78 @@ int UtcDaliTextFieldMarkupNestedUnderlineTags(void) END_TEST; } +int UtcDaliTextFieldMarkupNestedStrikethroughTags(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextFieldMarkupNestedStrikethroughTags "); + + TextField textField = TextField::New(); + + application.GetScene().Add(textField); + + std::string testText = "startABXYZCDEend"; + + 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 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 + {"ABXYZCDE", + 5u, + 8u, + { + Color::GREEN, + 5.0f, + true, + true, + }}, + + //Inner + {"XYZ", + 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; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp index 6c07302..1ac00b5 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp @@ -561,6 +561,78 @@ int UtcDaliTextLabelMarkupNestedUnderlineTags(void) END_TEST; } +int UtcDaliTextLabelMarkupNestedStrikethroughTags(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLabelMarkupNestedStrikethroughTags "); + + TextLabel textLabel = TextLabel::New(); + + application.GetScene().Add(textLabel); + + std::string testText = "startABXYZCDEend"; + + 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 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 + {"ABXYZCDE", + 5u, + 8u, + { + Color::GREEN, + 5.0f, + true, + true, + }}, + + //Inner + {"XYZ", + 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; diff --git a/dali-toolkit/internal/text/markup-processor-strikethrough.cpp b/dali-toolkit/internal/text/markup-processor-strikethrough.cpp index 622a624..2f0ea5d 100644 --- a/dali-toolkit/internal/text/markup-processor-strikethrough.cpp +++ b/dali-toolkit/internal/text/markup-processor-strikethrough.cpp @@ -71,6 +71,44 @@ void ProcessStrikethroughTag(const Tag& tag, StrikethroughCharacterRun& striketh } } +void OverrideNestedStrikethroughCharacterRuns(Vector& strikethroughCharacterRuns) +{ + // Handle nested tags + // The inner tag inherit the attributes of the outer tag and override them when defined in the inner tag. + // Example: + // outer tag before inner tag outer tag after + // "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::ConstIterator preIt = strikethroughCharacterRuns.Begin(); + + Vector::Iterator it = strikethroughCharacterRuns.Begin() + 1; + Vector::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 diff --git a/dali-toolkit/internal/text/markup-processor-strikethrough.h b/dali-toolkit/internal/text/markup-processor-strikethrough.h index d18966d..fca6d34 100644 --- a/dali-toolkit/internal/text/markup-processor-strikethrough.h +++ b/dali-toolkit/internal/text/markup-processor-strikethrough.h @@ -18,6 +18,12 @@ * */ +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + namespace Dali { namespace Toolkit @@ -52,6 +58,13 @@ void ProcessHeightAttribute(const Attribute& attribute, StrikethroughCharacterRu */ 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); + } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/markup-processor.cpp b/dali-toolkit/internal/text/markup-processor.cpp index 830d629..9c26b39 100644 --- a/dali-toolkit/internal/text/markup-processor.cpp +++ b/dali-toolkit/internal/text/markup-processor.cpp @@ -1179,6 +1179,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar // Handle the nested tags OverrideNestedUnderlinedCharacterRuns(markupProcessData.underlinedCharacterRuns); + OverrideNestedStrikethroughCharacterRuns(markupProcessData.strikethroughCharacterRuns); } } // namespace Text diff --git a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp index d9c4c86..e30564e 100644 --- a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -554,8 +554,8 @@ struct AtlasRenderer::Impl Vector::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 diff --git a/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.cpp b/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.cpp index b28f90f..76b8ce3 100644 --- a/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.cpp +++ b/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.cpp @@ -45,27 +45,34 @@ bool IsGlyphStrikethrough(GlyphIndex index, return false; } -float GetCurrentStrikethroughHeight(const Vector& strikethroughRuns, - Vector::ConstIterator currentStrikethroughGlyphRunIt, - const float strikethroughHeight) +StrikethroughStyleProperties GetCurrentStrikethroughProperties(GlyphIndex index, + const bool& isGlyphStrikethrough, + const Vector& strikethroughRuns, + Vector::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::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& strikethroughRuns, - Vector::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 diff --git a/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.h b/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.h index c5c5141..d9c86e4 100644 --- a/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.h +++ b/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.h @@ -46,21 +46,9 @@ bool IsGlyphStrikethrough(GlyphIndex index, Vector::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& strikethroughRuns, - Vector::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. @@ -68,10 +56,11 @@ float GetCurrentStrikethroughHeight(const Vector& * * @return the determined strikethrough properties */ -StrikethroughStyleProperties GetCurrentStrikethroughProperties(const bool& isGlyphStrikethrough, - const Vector& strikethroughRuns, - Vector::ConstIterator currentStrikethroughGlyphRunIt, - const StrikethroughStyleProperties& commonStrikethroughProperties); +StrikethroughStyleProperties GetCurrentStrikethroughProperties(GlyphIndex index, + const bool& isGlyphStrikethrough, + const Vector& strikethroughRuns, + Vector::ConstIterator& currentStrikethroughGlyphRunIt, + const StrikethroughStyleProperties& commonStrikethroughProperties); /** * @brief Calculate the current strikethrough height and update maximum strikethrough height diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.cpp b/dali-toolkit/internal/text/rendering/text-typesetter.cpp index afb279e..9d58934 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -991,8 +991,8 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, Vector::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 diff --git a/dali-toolkit/internal/text/strikethrough-style-properties.h b/dali-toolkit/internal/text/strikethrough-style-properties.h index a92f4c2..79597c9 100644 --- a/dali-toolkit/internal/text/strikethrough-style-properties.h +++ b/dali-toolkit/internal/text/strikethrough-style-properties.h @@ -76,6 +76,46 @@ struct StrikethroughStyleProperties 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.