From: ssabah Date: Sun, 6 Mar 2022 11:04:49 +0000 (+0300) Subject: Support character-spacing in span tag X-Git-Tag: dali_2.1.16~7 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=c49e595f12e9e56cd7c35262eb52ae1f2d9b685b;hp=1d6351bc6c29b125b71b266f4a8d0f25413e099d Support character-spacing in span tag Add Character-Spacing value attribute "char-space-value" to span tag. How to apply it in TextEditor: textEditor.SetProperty(Dali::Toolkit::TextEditor::Property::TEXT, "ABC EF\n" "ABC EF\n" "ABC EF\n"); 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/+/271789 Change-Id: I203c6e1f3a116ae557ffbc84859a121739e6b6c6 --- 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 5f7328f..f768255 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 @@ -1381,4 +1381,64 @@ int UtcDaliTextEditorMarkupCharacterSpacingTag(void) } END_TEST; +} + +int UtcDaliTextEditorMarkupSpanCharacterSpacing(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorMarkupSpanCharacterSpacing "); + + const Length EXPECTED_NUMBER_OF_GLYPHS = 21u; + + const float expandedCharSpacing = 10.0f; + const float condensedCharSpacing = -5.0f; + + std::string testText = + "ABC EF\n" + "ABC EF\n" + "ABC EF\n"; + + TextEditor textEditor = TextEditor::New(); + + textEditor.SetProperty(TextEditor::Property::TEXT, testText); + textEditor.SetProperty(TextEditor ::Property::ENABLE_MARKUP, true); + + application.GetScene().Add(textEditor); + + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextEditor& textEditorImpl = GetImpl(textEditor); + Text::ViewInterface& view = textEditorImpl.GetTextController()->GetView(); + + Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + Vector glyphs; + glyphs.Resize(numberOfGlyphs); + + Vector positions; + positions.Resize(numberOfGlyphs); + + float alignmentOffset = 0u; + numberOfGlyphs = view.GetGlyphs(glyphs.Begin(), + positions.Begin(), + alignmentOffset, + 0u, + numberOfGlyphs); + + const Length numberOfGlyphsOneLine = 7u; + for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++) + { + float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x; + + float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + } + + END_TEST; } \ No newline at end of file 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 f8210dc..da3ffc3 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 @@ -1290,4 +1290,64 @@ int UtcDaliTextFieldMarkupCharacterSpacingTag(void) } END_TEST; +} + +int UtcDaliTextFieldMarkupSpanCharacterSpacing(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextFieldMarkupSpanCharacterSpacing "); + + const Length EXPECTED_NUMBER_OF_GLYPHS = 21u; + + const float expandedCharSpacing = 10.0f; + const float condensedCharSpacing = -5.0f; + + std::string testText = + "ABC EF\n" + "ABC EF\n" + "ABC EF\n"; + + TextField textField = TextField::New(); + + textField.SetProperty(TextField::Property::TEXT, testText); + textField.SetProperty(TextField ::Property::ENABLE_MARKUP, true); + + application.GetScene().Add(textField); + + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextField& textFieldImpl = GetImpl(textField); + Text::ViewInterface& view = textFieldImpl.GetTextController()->GetView(); + + Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + Vector glyphs; + glyphs.Resize(numberOfGlyphs); + + Vector positions; + positions.Resize(numberOfGlyphs); + + float alignmentOffset = 0u; + numberOfGlyphs = view.GetGlyphs(glyphs.Begin(), + positions.Begin(), + alignmentOffset, + 0u, + numberOfGlyphs); + + const Length numberOfGlyphsOneLine = 7u; + for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++) + { + float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x; + + float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + } + + END_TEST; } \ No newline at end of file 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 2f1d1c6..d9a3c04 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 @@ -1276,4 +1276,65 @@ int UtcDaliTextLabelMarkupCharacterSpacingTag(void) } END_TEST; +} + +int UtcDaliTextLabelMarkupSpanCharacterSpacing(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLabelMarkupSpanCharacterSpacing "); + + const Length EXPECTED_NUMBER_OF_GLYPHS = 21u; + + const float expandedCharSpacing = 10.0f; + const float condensedCharSpacing = -5.0f; + + std::string testText = + "ABC EF\n" + "ABC EF\n" + "ABC EF\n"; + + TextLabel textLabel = TextLabel::New(); + + textLabel.SetProperty(TextLabel::Property::TEXT, testText); + textLabel.SetProperty(TextLabel ::Property::ENABLE_MARKUP, true); + textLabel.SetProperty(TextLabel::Property::MULTI_LINE, true); + + application.GetScene().Add(textLabel); + + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextLabel& textLabelImpl = GetImpl(textLabel); + Text::ViewInterface& view = textLabelImpl.GetTextController()->GetView(); + + Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + Vector glyphs; + glyphs.Resize(numberOfGlyphs); + + Vector positions; + positions.Resize(numberOfGlyphs); + + float alignmentOffset = 0u; + numberOfGlyphs = view.GetGlyphs(glyphs.Begin(), + positions.Begin(), + alignmentOffset, + 0u, + numberOfGlyphs); + + const Length numberOfGlyphsOneLine = 7u; + for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++) + { + float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x; + + float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + } + + END_TEST; } \ No newline at end of file diff --git a/dali-toolkit/internal/text/markup-processor-span.cpp b/dali-toolkit/internal/text/markup-processor-span.cpp index 1b3cdc2..19810ee 100644 --- a/dali-toolkit/internal/text/markup-processor-span.cpp +++ b/dali-toolkit/internal/text/markup-processor-span.cpp @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -57,20 +58,26 @@ const std::string XHTML_UNDERLINE_DASH_WIDTH_ATTRIBUTE("u-dash-width"); const std::string XHTML_STRIKETHROUGH_COLOR_ATTRIBUTE("s-color"); const std::string XHTML_STRIKETHROUGH_HEIGHT_ATTRIBUTE("s-height"); -} // namespace +//the character-spacing character's attributes +const std::string XHTML_CHARACTER_SPACING_VALUE_ATTRIBUTE("char-space-value"); + +//NOTE: the MAX_NUM_OF_ATTRIBUTES in "markup-processor.cpp" should be updated when add a new attribute for span tag. -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 +void ProcessSpanTag(const Tag& tag, + ColorRun& colorRun, + FontDescriptionRun& fontRun, + UnderlinedCharacterRun& underlinedCharacterRun, + ColorRun& backgroundColorRun, + StrikethroughCharacterRun& strikethroughRun, + CharacterSpacingCharacterRun& characterSpacingCharacterRun, + bool& isColorDefined, + bool& isFontDefined, + bool& isUnderlinedCharacterDefined, + bool& isBackgroundColorDefined, + bool& isStrikethroughDefined, + bool& isCharacterSpacingDefined) { for(Vector::ConstIterator it = tag.attributes.Begin(), endIt = tag.attributes.End(); @@ -149,6 +156,11 @@ void ProcessSpanTag(const Tag& tag, isStrikethroughDefined = true; ProcessHeightAttribute(attribute, strikethroughRun); } + else if(TokenComparison(XHTML_CHARACTER_SPACING_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + isCharacterSpacingDefined = true; + ProcessValueAttribute(attribute, characterSpacingCharacterRun); + } } } diff --git a/dali-toolkit/internal/text/markup-processor-span.h b/dali-toolkit/internal/text/markup-processor-span.h index 6c29554..5630fd3 100644 --- a/dali-toolkit/internal/text/markup-processor-span.h +++ b/dali-toolkit/internal/text/markup-processor-span.h @@ -36,23 +36,27 @@ struct MarkupProcessData; * @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] characterSpacingCharacterRun the character-spacing 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. + * @param[out] isCharacterSpacingDefined if the span has character-spacing defined. */ -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); +void ProcessSpanTag(const Tag& tag, + ColorRun& colorRun, + FontDescriptionRun& fontRun, + UnderlinedCharacterRun& underlinedCharacterRun, + ColorRun& backgroundColorRun, + StrikethroughCharacterRun& strikethroughRun, + CharacterSpacingCharacterRun& characterSpacingCharacterRun, + bool& isColorDefined, + bool& isFontDefined, + bool& isUnderlinedCharacterDefined, + bool& isBackgroundColorDefined, + bool& isStrikethroughDefined, + bool& isCharacterSpacingDefined); } // namespace Text diff --git a/dali-toolkit/internal/text/markup-processor.cpp b/dali-toolkit/internal/text/markup-processor.cpp index a11b303..1df19ca 100644 --- a/dali-toolkit/internal/text/markup-processor.cpp +++ b/dali-toolkit/internal/text/markup-processor.cpp @@ -85,7 +85,8 @@ 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 = 13u; ///< 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', 's-color' and 's-height' attrubutes. +// The MAX_NUM_OF_ATTRIBUTES is the number of attributes in span tag "markup-processor-span.cpp". Because it contains the maximum number of attributes in all tags. +const unsigned int MAX_NUM_OF_ATTRIBUTES = 14u; ///< 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', 's-color', 's-height' and 'char-space-value' attrubutes. const unsigned int DEFAULT_VECTOR_SIZE = 16u; ///< Default size of run vectors. #if defined(DEBUG_ENABLED) @@ -145,12 +146,14 @@ struct Span RunIndex underlinedCharacterRunIndex; RunIndex backgroundColorRunIndex; RunIndex strikethroughCharacterRunIndex; + RunIndex characterSpacingCharacterRunIndex; bool isColorDefined; bool isFontDefined; bool isUnderlinedCharacterDefined; bool isBackgroundColorDefined; bool isStrikethroughDefined; + bool isCharacterSpacingDefined; }; /** @@ -204,10 +207,12 @@ void Initialize(UnderlinedCharacterRun& underlinedCharacterRun) */ void Initialize(Span& span) { - span.colorRunIndex = 0u; - span.isColorDefined = false; - span.fontRunIndex = 0u; - span.isFontDefined = false; + span.colorRunIndex = 0u; + span.isColorDefined = false; + + span.fontRunIndex = 0u; + span.isFontDefined = false; + span.underlinedCharacterRunIndex = 0u; span.isUnderlinedCharacterDefined = false; span.backgroundColorRunIndex = 0u; @@ -216,6 +221,10 @@ void Initialize(Span& span) //strikethrough span.strikethroughCharacterRunIndex = 0u; span.isStrikethroughDefined = false; + + //characterSpacing + span.characterSpacingCharacterRunIndex = 0u; + span.isCharacterSpacingDefined = false; } /** @@ -752,20 +761,22 @@ void ProcessAnchorTag( * @param[in] tagReference The tagReference we should increment/decrement */ void ProcessSpanForRun( - 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) + const Tag& spanTag, + StyleStack& spanStack, + Vector& colorRuns, + Vector& fontRuns, + Vector& underlinedCharacterRuns, + Vector& backgroundColorRuns, + Vector& strikethroughCharacterRuns, + Vector& characterSpacingCharacterRuns, + RunIndex& colorRunIndex, + RunIndex& fontRunIndex, + RunIndex& underlinedCharacterRunIndex, + RunIndex& backgroundColorRunIndex, + RunIndex& strikethroughCharacterRunIndex, + RunIndex& characterSpacingCharacterRunIndex, + const CharacterIndex characterIndex, + int& tagReference) { if(!spanTag.isEndTag) { @@ -785,21 +796,26 @@ void ProcessSpanForRun( StrikethroughCharacterRun strikethroughCharacterRun; Initialize(strikethroughCharacterRun); + CharacterSpacingCharacterRun characterSpacingCharacterRun; + Initialize(characterSpacingCharacterRun); + 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; - strikethroughCharacterRun.characterRun.characterIndex = characterIndex; - - span.colorRunIndex = colorRunIndex; - span.fontRunIndex = fontRunIndex; - span.underlinedCharacterRunIndex = underlinedCharacterRunIndex; - span.backgroundColorRunIndex = backgroundColorRunIndex; - span.strikethroughCharacterRunIndex = strikethroughCharacterRunIndex; + colorRun.characterRun.characterIndex = characterIndex; + fontRun.characterRun.characterIndex = characterIndex; + underlinedCharacterRun.characterRun.characterIndex = characterIndex; + backgroundColorRun.characterRun.characterIndex = characterIndex; + strikethroughCharacterRun.characterRun.characterIndex = characterIndex; + characterSpacingCharacterRun.characterRun.characterIndex = characterIndex; + + span.colorRunIndex = colorRunIndex; + span.fontRunIndex = fontRunIndex; + span.underlinedCharacterRunIndex = underlinedCharacterRunIndex; + span.backgroundColorRunIndex = backgroundColorRunIndex; + span.strikethroughCharacterRunIndex = strikethroughCharacterRunIndex; + span.characterSpacingCharacterRunIndex = characterSpacingCharacterRunIndex; ProcessSpanTag(spanTag, colorRun, @@ -807,11 +823,13 @@ void ProcessSpanForRun( underlinedCharacterRun, backgroundColorRun, strikethroughCharacterRun, + characterSpacingCharacterRun, span.isColorDefined, span.isFontDefined, span.isUnderlinedCharacterDefined, span.isBackgroundColorDefined, - span.isStrikethroughDefined); + span.isStrikethroughDefined, + span.isCharacterSpacingDefined); // Push the span into the stack. spanStack.Push(span); @@ -852,6 +870,13 @@ void ProcessSpanForRun( ++strikethroughCharacterRunIndex; } + if(span.isCharacterSpacingDefined) + { + // Push the run in the logical model. + characterSpacingCharacterRuns.PushBack(characterSpacingCharacterRun); + ++characterSpacingCharacterRunIndex; + } + // Increase reference ++tagReference; } @@ -892,6 +917,12 @@ void ProcessSpanForRun( strikethroughCharacterRun.characterRun.numberOfCharacters = characterIndex - strikethroughCharacterRun.characterRun.characterIndex; } + if(span.isCharacterSpacingDefined) + { + CharacterSpacingCharacterRun& characterSpacingCharacterRun = *(characterSpacingCharacterRuns.Begin() + span.characterSpacingCharacterRunIndex); + characterSpacingCharacterRun.characterRun.numberOfCharacters = characterIndex - characterSpacingCharacterRun.characterRun.characterIndex; + } + --tagReference; } } @@ -1168,11 +1199,13 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar markupProcessData.underlinedCharacterRuns, markupProcessData.backgroundColorRuns, markupProcessData.strikethroughCharacterRuns, + markupProcessData.characterSpacingCharacterRuns, colorRunIndex, fontRunIndex, underlinedCharacterRunIndex, backgroundRunIndex, strikethroughCharacterRunIndex, + characterSpacingCharacterRunIndex, characterIndex, spanTagReference); }