From e6c8fad2c1ee24ce368976221941dfec12290b29 Mon Sep 17 00:00:00 2001 From: ssabah Date: Sun, 6 Mar 2022 18:14:19 +0300 Subject: [PATCH] Support the strikethrough and its attribute in span tag The attributes of strikethrough : - s-color How to apply it in TextEditor: textEditor.SetProperty(Dali::Toolkit::TextEditor::Property::TEXT, " hello world span tag nothing hello world s tag "); textEditor.SetProperty(Dali::Toolkit::TextEditor::Property::ENABLE_MARKUP, true); This patch should be preceded by the patch below: https://review.tizen.org/gerrit/c/platform/core/uifw/dali-toolkit/+/272018 Change-Id: I87bdf96565a22d90d9f1d1000cb719fbfd6dbc84 --- .../utc-Dali-TextEditor-internal.cpp | 70 +++++++++++ .../utc-Dali-TextField-internal.cpp | 70 +++++++++++ .../utc-Dali-TextLabel-internal.cpp | 70 +++++++++++ .../internal/text/markup-processor-span.cpp | 31 +++-- dali-toolkit/internal/text/markup-processor-span.h | 22 ++-- dali-toolkit/internal/text/markup-processor.cpp | 130 +++++++++++++++------ 6 files changed, 339 insertions(+), 54 deletions(-) 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 3ff87d6..14bdfa0 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,76 @@ int UtcDaliTextEditorMarkupNestedUnderlineTags(void) END_TEST; } +int UtcDaliTextEditorMarkupSpanStrikethrough(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorMarkupSpanStrikethrough "); + + TextEditor textEditor = TextEditor::New(); + + application.GetScene().Add(textEditor); + + std::string testText = + "startABC1then" + "ABC2then" + "ABC3end"; + + 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[] = + { + + {"ABC2then", + 13u, + 4u, + {Color::BLUE, + 0u, + true, + false}}, + + {"ABC3", + 21u, + 4u, + {Color::GREEN, + 0u, + true, + false}}, + + }; + + 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 UtcDaliTextEditorFontPointSizeLargerThanAtlas(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 42ca11c..18e2b06 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,76 @@ int UtcDaliTextFieldMarkupNestedUnderlineTags(void) END_TEST; } +int UtcDaliTextFieldMarkupSpanStrikethrough(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextFieldMarkupSpanStrikethrough "); + + TextField textField = TextField::New(); + + application.GetScene().Add(textField); + + std::string testText = + "startABC1then" + "ABC2then" + "ABC3end"; + + 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[] = + { + + {"ABC2then", + 13u, + 4u, + {Color::BLUE, + 0u, + true, + false}}, + + {"ABC3", + 21u, + 4u, + {Color::GREEN, + 0u, + true, + false}}, + + }; + + 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 UtcDaliTextFieldFontPointSizeLargerThanAtlas(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 b1bba97..2bd7df1 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,76 @@ int UtcDaliTextLabelMarkupNestedUnderlineTags(void) END_TEST; } +int UtcDaliTextLabelMarkupSpanStrikethrough(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLabelMarkupSpanStrikethrough "); + + TextLabel textLabel = TextLabel::New(); + + application.GetScene().Add(textLabel); + + std::string testText = + "startABC1then" + "ABC2then" + "ABC3end"; + + 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[] = + { + + {"ABC2then", + 13u, + 4u, + {Color::BLUE, + 0u, + true, + false}}, + + {"ABC3", + 21u, + 4u, + {Color::GREEN, + 0u, + true, + false}}, + + }; + + 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 UtcDaliTextLabelBackgroundTag(void) { ToolkitTestApplication application; diff --git a/dali-toolkit/internal/text/markup-processor-span.cpp b/dali-toolkit/internal/text/markup-processor-span.cpp index 240cd62..636c331 100644 --- a/dali-toolkit/internal/text/markup-processor-span.cpp +++ b/dali-toolkit/internal/text/markup-processor-span.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include namespace Dali @@ -51,17 +52,24 @@ const std::string XHTML_UNDERLINE_HEIGHT_ATTRIBUTE("u-height"); const std::string XHTML_UNDERLINE_TYPE_ATTRIBUTE("u-type"); const std::string XHTML_UNDERLINE_DASH_GAP_ATTRIBUTE("u-dash-gap"); const std::string XHTML_UNDERLINE_DASH_WIDTH_ATTRIBUTE("u-dash-width"); + +//the strikethroughed character's attributes +const std::string XHTML_STRIKETHROUGH_COLOR_ATTRIBUTE("s-color"); + } // namespace -void ProcessSpanTag(const Tag& tag, - ColorRun& colorRun, - FontDescriptionRun& fontRun, - UnderlinedCharacterRun& underlinedCharacterRun, - ColorRun& backgroundColorRun, - bool& isColorDefined, - bool& isFontDefined, - bool& isUnderlinedCharacterDefined, - bool& isBackgroundColorDefined) +void ProcessSpanTag(const Tag& tag, + ColorRun& colorRun, + FontDescriptionRun& fontRun, + UnderlinedCharacterRun& underlinedCharacterRun, + ColorRun& backgroundColorRun, + StrikethroughCharacterRun& strikethroughRun, + bool& isColorDefined, + bool& isFontDefined, + bool& isUnderlinedCharacterDefined, + bool& isBackgroundColorDefined, + bool& isStrikethroughDefined) + { for(Vector::ConstIterator it = tag.attributes.Begin(), endIt = tag.attributes.End(); @@ -130,6 +138,11 @@ void ProcessSpanTag(const Tag& tag, isUnderlinedCharacterDefined = true; ProcessDashWidthAttribute(attribute, underlinedCharacterRun); } + else if(TokenComparison(XHTML_STRIKETHROUGH_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + isStrikethroughDefined = true; + ProcessColorAttribute(attribute, strikethroughRun); + } } } diff --git a/dali-toolkit/internal/text/markup-processor-span.h b/dali-toolkit/internal/text/markup-processor-span.h index d6b514a..6c29554 100644 --- a/dali-toolkit/internal/text/markup-processor-span.h +++ b/dali-toolkit/internal/text/markup-processor-span.h @@ -35,20 +35,24 @@ struct MarkupProcessData; * @param[out] fontRun the font run to be filled. * @param[out] underlinedCharacterRun the underlined character run to be filled. * @param[out] backgroundColorRun the background color run to be filled. + * @param[out] strikethroughRun the strikethrough run to be filled. * @param[out] isColorDefined if the span has color defined. * @param[out] isFontDefined if the span has font defined. * @param[out] isUnderlinedCharacterDefined if the span has underlined-character defined. * @param[out] isBackgroundColorDefined if the span has background color defined. + * @param[out] isStrikethroughDefined if the span has strikethrough defined. */ -void ProcessSpanTag(const Tag& tag, - ColorRun& colorRun, - FontDescriptionRun& fontRun, - UnderlinedCharacterRun& underlinedCharacterRun, - ColorRun& backgroundColorRun, - bool& isColorDefined, - bool& isFontDefined, - bool& isUnderlinedCharacterDefined, - bool& isBackgroundColorDefined); +void ProcessSpanTag(const Tag& tag, + ColorRun& colorRun, + FontDescriptionRun& fontRun, + UnderlinedCharacterRun& underlinedCharacterRun, + ColorRun& backgroundColorRun, + StrikethroughCharacterRun& strikethroughRun, + bool& isColorDefined, + bool& isFontDefined, + bool& isUnderlinedCharacterDefined, + bool& isBackgroundColorDefined, + bool& isStrikethroughDefined); } // namespace Text diff --git a/dali-toolkit/internal/text/markup-processor.cpp b/dali-toolkit/internal/text/markup-processor.cpp index 1671075..f5b90dc 100644 --- a/dali-toolkit/internal/text/markup-processor.cpp +++ b/dali-toolkit/internal/text/markup-processor.cpp @@ -83,7 +83,7 @@ const char NEW_LINE = 0x0A; // ASCII value of the newline. // Range 3 0x10000u < XHTML_DECIMAL_ENTITY_RANGE <= 0x10FFFFu const unsigned long XHTML_DECIMAL_ENTITY_RANGE[] = {0x0u, 0xD7FFu, 0xE000u, 0xFFFDu, 0x10000u, 0x10FFFFu}; -const unsigned int MAX_NUM_OF_ATTRIBUTES = 11u; ///< The span tag has the 'font-family', 'font-size' 'font-weight', 'font-width', 'font-slant','text-color', 'u-color', 'u-height','u-type','u-dash-gap'and 'u-dash-width' attrubutes. +const unsigned int MAX_NUM_OF_ATTRIBUTES = 12u; ///< The span tag has the 'font-family', 'font-size' 'font-weight', 'font-width', 'font-slant','text-color', 'u-color', 'u-height','u-type','u-dash-gap', 'u-dash-width' and 's-color' attrubutes. const unsigned int DEFAULT_VECTOR_SIZE = 16u; ///< Default size of run vectors. #if defined(DEBUG_ENABLED) @@ -142,10 +142,13 @@ struct Span RunIndex fontRunIndex; RunIndex underlinedCharacterRunIndex; RunIndex backgroundColorRunIndex; - bool isColorDefined; - bool isFontDefined; - bool isUnderlinedCharacterDefined; - bool isBackgroundColorDefined; + RunIndex strikethroughCharacterRunIndex; + + bool isColorDefined; + bool isFontDefined; + bool isUnderlinedCharacterDefined; + bool isBackgroundColorDefined; + bool isStrikethroughDefined; }; /** @@ -207,6 +210,10 @@ void Initialize(Span& span) span.isUnderlinedCharacterDefined = false; span.backgroundColorRunIndex = 0u; span.isBackgroundColorDefined = false; + + //strikethrough + span.strikethroughCharacterRunIndex = 0u; + span.isStrikethroughDefined = false; } /** @@ -718,27 +725,33 @@ void ProcessAnchorTag( * @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[inout] spanStack The spans stack + * @param[inout] colorRuns The container containing all the color runs + * @param[inout] fontRuns The container containing all the font description runs + * @param[inout] underlinedCharacterRuns The container containing all the underlined character runs + * @param[inout] strikethroughCharacterRuns The container containing all the strikethroughed character runs + * @param[inout] colorRunIndex The color run index + * @param[inout] fontRunIndex The font run index + * @param[inout] underlinedCharacterRunIndex The underlined character run index + * @param[inout] strikethroughCharacterRunIndex The strikethroughed character run index * @param[in] characterIndex The current character index * @param[in] tagReference The tagReference we should increment/decrement */ void ProcessSpanForRun( - const Tag& spanTag, - StyleStack& spanStack, - Vector& colorRuns, - Vector& fontRuns, - Vector& underlinedCharacterRuns, - Vector& backgroundColorRuns, - RunIndex& colorRunIndex, - RunIndex& fontRunIndex, - RunIndex& underlinedCharacterRunIndex, - RunIndex& backgroundColorRunIndex, - const CharacterIndex characterIndex, - int& tagReference) + const Tag& spanTag, + StyleStack& spanStack, + Vector& colorRuns, + Vector& fontRuns, + Vector& underlinedCharacterRuns, + Vector& backgroundColorRuns, + Vector& strikethroughCharacterRuns, + RunIndex& colorRunIndex, + RunIndex& fontRunIndex, + RunIndex& underlinedCharacterRunIndex, + RunIndex& backgroundColorRunIndex, + RunIndex& strikethroughCharacterRunIndex, + const CharacterIndex characterIndex, + int& tagReference) { if(!spanTag.isEndTag) { @@ -755,21 +768,36 @@ void ProcessSpanForRun( ColorRun backgroundColorRun; Initialize(backgroundColorRun); + StrikethroughCharacterRun strikethroughCharacterRun; + Initialize(strikethroughCharacterRun); + Span span; Initialize(span); // Fill the run with the parameters. - colorRun.characterRun.characterIndex = characterIndex; - fontRun.characterRun.characterIndex = characterIndex; - underlinedCharacterRun.characterRun.characterIndex = characterIndex; - backgroundColorRun.characterRun.characterIndex = characterIndex; - - span.colorRunIndex = colorRunIndex; - span.fontRunIndex = fontRunIndex; - span.underlinedCharacterRunIndex = underlinedCharacterRunIndex; - span.backgroundColorRunIndex = backgroundColorRunIndex; - - ProcessSpanTag(spanTag, colorRun, fontRun, underlinedCharacterRun, backgroundColorRun, span.isColorDefined, span.isFontDefined, span.isUnderlinedCharacterDefined, span.isBackgroundColorDefined); + colorRun.characterRun.characterIndex = characterIndex; + fontRun.characterRun.characterIndex = characterIndex; + underlinedCharacterRun.characterRun.characterIndex = characterIndex; + backgroundColorRun.characterRun.characterIndex = characterIndex; + strikethroughCharacterRun.characterRun.characterIndex = characterIndex; + + span.colorRunIndex = colorRunIndex; + span.fontRunIndex = fontRunIndex; + span.underlinedCharacterRunIndex = underlinedCharacterRunIndex; + span.backgroundColorRunIndex = backgroundColorRunIndex; + span.strikethroughCharacterRunIndex = strikethroughCharacterRunIndex; + + ProcessSpanTag(spanTag, + colorRun, + fontRun, + underlinedCharacterRun, + backgroundColorRun, + strikethroughCharacterRun, + span.isColorDefined, + span.isFontDefined, + span.isUnderlinedCharacterDefined, + span.isBackgroundColorDefined, + span.isStrikethroughDefined); // Push the span into the stack. spanStack.Push(span); @@ -803,6 +831,13 @@ void ProcessSpanForRun( ++backgroundColorRunIndex; } + if(span.isStrikethroughDefined) + { + // Push the run in the logical model. + strikethroughCharacterRuns.PushBack(strikethroughCharacterRun); + ++strikethroughCharacterRunIndex; + } + // Increase reference ++tagReference; } @@ -837,6 +872,12 @@ void ProcessSpanForRun( backgroundColorRun.characterRun.numberOfCharacters = characterIndex - backgroundColorRun.characterRun.characterIndex; } + if(span.isStrikethroughDefined) + { + StrikethroughCharacterRun& strikethroughCharacterRun = *(strikethroughCharacterRuns.Begin() + span.strikethroughCharacterRunIndex); + strikethroughCharacterRun.characterRun.numberOfCharacters = characterIndex - strikethroughCharacterRun.characterRun.characterIndex; + } + --tagReference; } } @@ -845,10 +886,11 @@ void ProcessSpanForRun( /** * @brief Resizes the model's vectors * - * @param[in/out] markupProcessData The markup process data + * @param[inout] 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] strikethroughCharacterRunIndex The strikethroughed character run index * @param[in] backgroundRunIndex The background run index * @param[in] boundedParagraphRunIndex The bounded paragraph run index * @@ -857,12 +899,14 @@ void ResizeModelVectors(MarkupProcessData& markupProcessData, const RunIndex fontRunIndex, const RunIndex colorRunIndex, const RunIndex underlinedCharacterRunIndex, + const RunIndex strikethroughCharacterRunIndex, const RunIndex backgroundRunIndex, const RunIndex boundedParagraphRunIndex) { markupProcessData.fontRuns.Resize(fontRunIndex); markupProcessData.colorRuns.Resize(colorRunIndex); markupProcessData.underlinedCharacterRuns.Resize(underlinedCharacterRunIndex); + markupProcessData.strikethroughCharacterRuns.Resize(strikethroughCharacterRunIndex); markupProcessData.backgroundColorRuns.Resize(backgroundRunIndex); markupProcessData.boundedParagraphRuns.Resize(boundedParagraphRunIndex); @@ -1007,6 +1051,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar markupProcessData.fontRuns.Reserve(DEFAULT_VECTOR_SIZE); markupProcessData.underlinedCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE); markupProcessData.backgroundColorRuns.Reserve(DEFAULT_VECTOR_SIZE); + markupProcessData.strikethroughCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE); // Get the mark-up string buffer. const char* markupStringBuffer = markupString.c_str(); @@ -1096,7 +1141,20 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar } else if(TokenComparison(XHTML_SPAN_TAG, tag.buffer, tag.length)) { - ProcessSpanForRun(tag, spanStack, markupProcessData.colorRuns, markupProcessData.fontRuns, markupProcessData.underlinedCharacterRuns, markupProcessData.backgroundColorRuns, colorRunIndex, fontRunIndex, underlinedCharacterRunIndex, backgroundRunIndex, characterIndex, spanTagReference); + ProcessSpanForRun(tag, + spanStack, + markupProcessData.colorRuns, + markupProcessData.fontRuns, + markupProcessData.underlinedCharacterRuns, + markupProcessData.backgroundColorRuns, + markupProcessData.strikethroughCharacterRuns, + colorRunIndex, + fontRunIndex, + underlinedCharacterRunIndex, + backgroundRunIndex, + strikethroughCharacterRunIndex, + characterIndex, + spanTagReference); } else if(TokenComparison(XHTML_STRIKETHROUGH_TAG, tag.buffer, tag.length)) { @@ -1117,7 +1175,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar } // Resize the model's vectors. - ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, backgroundRunIndex, boundedParagraphRunIndex); + ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, strikethroughCharacterRunIndex, backgroundRunIndex, boundedParagraphRunIndex); // Handle the nested tags OverrideNestedUnderlinedCharacterRuns(markupProcessData.underlinedCharacterRuns); -- 2.7.4