From a8d266857c0a46aed1acdb147f84271b76ff7226 Mon Sep 17 00:00:00 2001 From: abdullah Date: Wed, 9 Mar 2022 13:27:50 +0300 Subject: [PATCH] Support paragraph attribute: relative line height

Hello

World Change-Id: I3824dd0d39021222a94e3122c4d88d94da5bc0b2 --- .../src/dali-toolkit/utc-Dali-TextEditor.cpp | 49 ++++++++++++ .../src/dali-toolkit/utc-Dali-TextLabel.cpp | 52 ++++++++++++ dali-toolkit/internal/text/bounded-paragraph-run.h | 6 +- .../internal/text/layouts/layout-engine.cpp | 92 +++++++++++++++++++--- .../internal/text/markup-processor-paragraph.cpp | 14 +++- .../internal/text/markup-processor-paragraph.h | 8 ++ 6 files changed, 208 insertions(+), 13 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index 9d9567b..fe83ae8 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp @@ -5765,6 +5765,55 @@ int UtcDaliToolkitTextEditorUnderlineTypesGeneration3(void) END_TEST; } +int UtcDaliToolkitTextEditorMarkupRelativeLineHeight(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliToolkitTextEditorMarkupRelativeLineHeight"); + + TextEditor editor = TextEditor::New(); + editor.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f)); + editor.SetProperty(TextEditor::Property::POINT_SIZE, 10); + editor.SetProperty(TextEditor::Property::TEXT, "line 1\nline 2\nline 3\nline 4\nline 5"); + editor.SetProperty(DevelTextEditor::Property::RELATIVE_LINE_SIZE, 1.0f); + editor.SetProperty(DevelTextEditor::Property::ELLIPSIS, false); + editor.SetProperty(TextEditor::Property::ENABLE_MARKUP, true); + + TextEditor editorSingleLineParagraph = TextEditor::New(); + editorSingleLineParagraph.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f)); + editorSingleLineParagraph.SetProperty(TextEditor::Property::POINT_SIZE, 10); + editorSingleLineParagraph.SetProperty(TextEditor::Property::TEXT, "

line 1

line 2

line 3

line 4

line 5"); + editorSingleLineParagraph.SetProperty(DevelTextEditor::Property::RELATIVE_LINE_SIZE, 1.0f); + editorSingleLineParagraph.SetProperty(DevelTextEditor::Property::ELLIPSIS, false); + editorSingleLineParagraph.SetProperty(TextEditor::Property::ENABLE_MARKUP, true); + + TextEditor editorMultiLineParagraph = TextEditor::New(); + editorMultiLineParagraph.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f)); + editorMultiLineParagraph.SetProperty(TextEditor::Property::POINT_SIZE, 10); + editorMultiLineParagraph.SetProperty(TextEditor::Property::TEXT, "

line 1

line\n2

line 3

line\n4

line 5"); + editorMultiLineParagraph.SetProperty(DevelTextEditor::Property::RELATIVE_LINE_SIZE, 1.0f); + editorMultiLineParagraph.SetProperty(DevelTextEditor::Property::ELLIPSIS, false); + editorMultiLineParagraph.SetProperty(TextEditor::Property::ENABLE_MARKUP, true); + + application.GetScene().Add(editor); + application.GetScene().Add(editorSingleLineParagraph); + application.GetScene().Add(editorMultiLineParagraph); + application.SendNotification(); + application.Render(); + + Vector3 naturalSize = editor.GetNaturalSize(); + Vector3 relativeSingleNaturalSize = editorSingleLineParagraph.GetNaturalSize(); + Vector3 relativeMultiNaturalSize = editorMultiLineParagraph.GetNaturalSize(); + + float lineSize = naturalSize.y / 5.0f; //total size/number of lines + + //no effect of relative line size for paragraph with single line + DALI_TEST_EQUALS(naturalSize.y, relativeSingleNaturalSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + DALI_TEST_EQUALS(lineSize*8.5f, relativeMultiNaturalSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + END_TEST; +} + int UtcDaliToolkitTextEditorRelativeLineHeight(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index bbd3d77..30aaade 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -2632,6 +2632,58 @@ int UtcDaliToolkitTextLabelStrikethroughGeneration(void) END_TEST; } +int UtcDaliToolkitTextLabelMarkupRelativeLineHeight(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliToolkitTextLabelMarkupRelativeLineHeight"); + + TextLabel label = TextLabel::New(); + label.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f)); + label.SetProperty(TextLabel::Property::POINT_SIZE, 10); + label.SetProperty(TextLabel::Property::MULTI_LINE, true); + label.SetProperty(TextLabel::Property::TEXT, "line 1\nline 2\nline 3\nline 4\nline 5"); + label.SetProperty(DevelTextLabel::Property::RELATIVE_LINE_SIZE, 1.0f); + label.SetProperty(TextLabel::Property::ELLIPSIS, false); + label.SetProperty(TextLabel::Property::ENABLE_MARKUP, true); + + TextLabel labelSingleLineParagraph = TextLabel::New(); + labelSingleLineParagraph.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f)); + labelSingleLineParagraph.SetProperty(TextLabel::Property::POINT_SIZE, 10); + labelSingleLineParagraph.SetProperty(TextLabel::Property::MULTI_LINE, true); + labelSingleLineParagraph.SetProperty(TextLabel::Property::TEXT, "

line 1

line 2

line 3

line 4

line 5"); + labelSingleLineParagraph.SetProperty(DevelTextLabel::Property::RELATIVE_LINE_SIZE, 1.0f); + labelSingleLineParagraph.SetProperty(TextLabel::Property::ELLIPSIS, false); + labelSingleLineParagraph.SetProperty(TextLabel::Property::ENABLE_MARKUP, true); + + TextLabel labelMultiLineParagraph = TextLabel::New(); + labelMultiLineParagraph.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f)); + labelMultiLineParagraph.SetProperty(TextLabel::Property::POINT_SIZE, 10); + labelMultiLineParagraph.SetProperty(TextLabel::Property::MULTI_LINE, true); + labelMultiLineParagraph.SetProperty(TextLabel::Property::TEXT, "

line 1

line\n2

line 3

line\n4

line 5"); + labelMultiLineParagraph.SetProperty(DevelTextLabel::Property::RELATIVE_LINE_SIZE, 1.0f); + labelMultiLineParagraph.SetProperty(TextLabel::Property::ELLIPSIS, false); + labelMultiLineParagraph.SetProperty(TextLabel::Property::ENABLE_MARKUP, true); + + application.GetScene().Add(label); + application.GetScene().Add(labelSingleLineParagraph); + application.GetScene().Add(labelMultiLineParagraph); + application.SendNotification(); + application.Render(); + + Vector3 naturalSize = label.GetNaturalSize(); + Vector3 relativeSingleNaturalSize = labelSingleLineParagraph.GetNaturalSize(); + Vector3 relativeMultiNaturalSize = labelMultiLineParagraph.GetNaturalSize(); + + float lineSize = naturalSize.y / 5.0f; //total size/number of lines + + //no effect of relative line size for paragraph with single line + DALI_TEST_EQUALS(naturalSize.y, relativeSingleNaturalSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + DALI_TEST_EQUALS(lineSize*8.5f, relativeMultiNaturalSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + END_TEST; +} + int UtcDaliToolkitTextLabelRelativeLineHeight(void) { ToolkitTestApplication application; diff --git a/dali-toolkit/internal/text/bounded-paragraph-run.h b/dali-toolkit/internal/text/bounded-paragraph-run.h index ec15ff4..4b3150e 100644 --- a/dali-toolkit/internal/text/bounded-paragraph-run.h +++ b/dali-toolkit/internal/text/bounded-paragraph-run.h @@ -48,13 +48,17 @@ struct BoundedParagraphRun BoundedParagraphRun() : characterRun{}, horizontalAlignment(Text::HorizontalAlignment::BEGIN), - horizontalAlignmentDefined{false} + relativeLineSize(1), + horizontalAlignmentDefined{false}, + relativeLineSizeDefined(false) { } CharacterRun characterRun; ///< The initial character index within the whole text and the number of characters of the run. Text::HorizontalAlignment::Type horizontalAlignment; ///< The paragraph horizontal alignment. Values "BEGIN" "CENTER" "END". + float relativeLineSize; ///< The relative line height to be used for this paragaraph. bool horizontalAlignmentDefined : 1; ///< Whether the horizontal alignment is defined. + bool relativeLineSizeDefined : 1; ///< Whether the relative line height is defined for this paragraph. }; } // namespace Text diff --git a/dali-toolkit/internal/text/layouts/layout-engine.cpp b/dali-toolkit/internal/text/layouts/layout-engine.cpp index aff78c6..b701086 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.cpp +++ b/dali-toolkit/internal/text/layouts/layout-engine.cpp @@ -96,7 +96,8 @@ struct LineLayout glyphIndexInSecondHalfLine{0u}, characterIndexInSecondHalfLine{0u}, numberOfGlyphsInSecondHalfLine{0u}, - numberOfCharactersInSecondHalfLine{0u} + numberOfCharactersInSecondHalfLine{0u}, + relativeLineSize{1.0f} { } @@ -119,6 +120,7 @@ struct LineLayout characterIndexInSecondHalfLine = 0u; numberOfGlyphsInSecondHalfLine = 0u; numberOfCharactersInSecondHalfLine = 0u; + relativeLineSize = 1.0f; } GlyphIndex glyphIndex; ///< Index of the first glyph to be laid-out. @@ -139,6 +141,8 @@ struct LineLayout CharacterIndex characterIndexInSecondHalfLine; ///< Index of the first character to be laid-out for the second half of line. Length numberOfGlyphsInSecondHalfLine; ///< The number of glyph which fit in one line for the second half of line. Length numberOfCharactersInSecondHalfLine; ///< The number of characters which fit in one line for the second half of line. + + float relativeLineSize; ///< The relative line size to be applied for this line. }; struct LayoutBidiParameters @@ -172,9 +176,10 @@ struct Engine::Impl * @brief get the line spacing. * * @param[in] textSize The text size. + * @param[in] relativeLineSize The relative line size to be applied. * @return the line spacing value. */ - float GetLineSpacing(float textSize) + float GetLineSpacing(float textSize, float relativeLineSize) { float lineSpacing; float relTextSize; @@ -187,10 +192,10 @@ struct Engine::Impl lineSpacing += mDefaultLineSpacing; //subtract line spcaing if relativeLineSize < 1 & larger than min height - relTextSize = textSize * mRelativeLineSize; + relTextSize = textSize * relativeLineSize; if(relTextSize > mDefaultLineSize) { - if(mRelativeLineSize < 1) + if(relativeLineSize < 1) { //subtract the difference (always will be positive) lineSpacing -= (textSize - relTextSize); @@ -239,7 +244,7 @@ struct Engine::Impl // Sets the minimum descender. lineLayout.descender = std::min(lineLayout.descender, fontMetrics.descender); - lineLayout.lineSpacing = GetLineSpacing(lineLayout.ascender + -lineLayout.descender); + lineLayout.lineSpacing = GetLineSpacing(lineLayout.ascender + -lineLayout.descender, lineLayout.relativeLineSize); } /** @@ -727,6 +732,8 @@ struct Engine::Impl // It needs to add as well space for the cursor if the text is in edit mode and extra space in case the text is outlined. tmpLineLayout.penX = -glyphMetrics.xBearing + mCursorWidth + outlineWidth; + tmpLineLayout.relativeLineSize = lineLayout.relativeLineSize; + // Calculate the line height if there is no characters. FontId lastFontId = glyphMetrics.fontId; UpdateLineHeight(glyphMetrics, tmpLineLayout); @@ -1253,6 +1260,9 @@ struct Engine::Impl LineRun* lineRun = nullptr; LineLayout ellipsisLayout; + + ellipsisLayout.relativeLineSize = layout.relativeLineSize; + if(0u != numberOfLines) { // Get the last line and layout it again with the 'completelyFill' flag to true. @@ -1409,7 +1419,7 @@ struct Engine::Impl lineRun.direction = layout.direction; lineRun.ellipsis = false; - lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender); + lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender, layout.relativeLineSize); // Update the actual size. if(lineRun.width > layoutSize.width) @@ -1463,7 +1473,11 @@ struct Engine::Impl lineRun.direction = LTR; lineRun.ellipsis = false; - lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender); + BoundedParagraphRun currentParagraphRun; + LineLayout tempLineLayout; + (GetBoundedParagraph(layoutParameters.textModel->GetBoundedParagraphRuns(), characterIndex, currentParagraphRun) ? SetRelativeLineSize(¤tParagraphRun, tempLineLayout) : SetRelativeLineSize(nullptr, tempLineLayout)); + + lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender, tempLineLayout.relativeLineSize); layoutSize.height += GetLineHeight(lineRun, true); } @@ -1523,6 +1537,51 @@ struct Engine::Impl } } + /** + * @brief Sets the relative line size for the LineLayout + * + * @param[in] currentParagraphRun Contains the bounded paragraph for this line layout. + * @param[in,out] lineLayout The line layout to be updated. + */ + void SetRelativeLineSize(BoundedParagraphRun* currentParagraphRun, LineLayout& lineLayout) + { + lineLayout.relativeLineSize = mRelativeLineSize; + + if(currentParagraphRun != nullptr && currentParagraphRun->relativeLineSizeDefined) + { + lineLayout.relativeLineSize = currentParagraphRun->relativeLineSize; + } + } + + /** + * @brief Get the bounded paragraph for the characterIndex if exists. + * + * @param[in] boundedParagraphRuns The bounded paragraph list to search in. + * @param[in] characterIndex The character index to get bounded paragraph for. + * @param[out] currentParagraphRun Contains the bounded paragraph if found for the characterIndex. + * + * @return returns true if a bounded paragraph was found. + */ + bool GetBoundedParagraph(const Vector boundedParagraphRuns, CharacterIndex characterIndex, BoundedParagraphRun& currentParagraphRun) + { + for(Vector::Iterator it = boundedParagraphRuns.Begin(), + endIt = boundedParagraphRuns.End(); + it != endIt; + ++it) + { + BoundedParagraphRun& tempParagraphRun = *it; + + if(characterIndex >= tempParagraphRun.characterRun.characterIndex && + characterIndex < (tempParagraphRun.characterRun.characterIndex + tempParagraphRun.characterRun.numberOfCharacters)) + { + currentParagraphRun = tempParagraphRun; + return true; + } + } + + return false; + } + bool LayoutText(Parameters& layoutParameters, Size& layoutSize, bool elideTextEnabled, @@ -1541,7 +1600,8 @@ struct Engine::Impl layoutParameters.textModel->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(0u); layoutParameters.textModel->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(0u); - Vector& lines = layoutParameters.textModel->mVisualModel->mLines; + Vector& lines = layoutParameters.textModel->mVisualModel->mLines; + const Vector& boundedParagraphRuns = layoutParameters.textModel->GetBoundedParagraphRuns(); if(0u == layoutParameters.numberOfGlyphs) { @@ -1601,7 +1661,7 @@ struct Engine::Impl // Retrieve BiDi info. const bool hasBidiParagraphs = !layoutParameters.textModel->mLogicalModel->mBidirectionalParagraphInfo.Empty(); - const CharacterIndex* const glyphsToCharactersBuffer = hasBidiParagraphs ? layoutParameters.textModel->mVisualModel->mGlyphsToCharacters.Begin() : nullptr; + const CharacterIndex* const glyphsToCharactersBuffer = layoutParameters.textModel->mVisualModel->mGlyphsToCharacters.Begin(); const Vector& bidirectionalParagraphsInfo = layoutParameters.textModel->mLogicalModel->mBidirectionalParagraphInfo; const Vector& bidirectionalLinesInfo = layoutParameters.textModel->mLogicalModel->mBidirectionalLineInfo; @@ -1705,6 +1765,10 @@ struct Engine::Impl LineLayout layout; layout.direction = layoutBidiParameters.paragraphDirection; layout.glyphIndex = index; + + BoundedParagraphRun currentParagraphRun; + (GetBoundedParagraph(boundedParagraphRuns, *(glyphsToCharactersBuffer + index), currentParagraphRun) ? SetRelativeLineSize(¤tParagraphRun, layout) : SetRelativeLineSize(nullptr, layout)); + GetLineLayoutForBox(layoutParameters, layoutBidiParameters, layout, @@ -1719,6 +1783,14 @@ struct Engine::Impl DALI_LOG_INFO(gLogFilter, Debug::Verbose, " number of characters %d\n", layout.numberOfCharacters); DALI_LOG_INFO(gLogFilter, Debug::Verbose, " length %f\n", layout.length); + CharacterIndex lastCharacterInParagraph = currentParagraphRun.characterRun.characterIndex + currentParagraphRun.characterRun.numberOfCharacters - 1; + + //check if this is the last line in paragraph, if false we should use the default relative line size (the one set using the property) + if(lastCharacterInParagraph >= layout.characterIndex && lastCharacterInParagraph < layout.characterIndex+layout.numberOfCharacters) + { + layout.relativeLineSize = mRelativeLineSize; + } + if(0u == layout.numberOfGlyphs + layout.numberOfGlyphsInSecondHalfLine) { // The width is too small and no characters are laid-out. @@ -1862,7 +1934,7 @@ struct Engine::Impl } // Updates the vertical pen's position. - penY += -layout.descender + layout.lineSpacing + GetLineSpacing(layout.ascender + -layout.descender); + penY += -layout.descender + layout.lineSpacing + GetLineSpacing(layout.ascender + -layout.descender, layout.relativeLineSize); // Increase the glyph index. index = nextIndex; diff --git a/dali-toolkit/internal/text/markup-processor-paragraph.cpp b/dali-toolkit/internal/text/markup-processor-paragraph.cpp index 35a1cc5..859547e 100644 --- a/dali-toolkit/internal/text/markup-processor-paragraph.cpp +++ b/dali-toolkit/internal/text/markup-processor-paragraph.cpp @@ -34,7 +34,8 @@ namespace Text namespace { const std::string XHTML_ALIGN_ATTRIBUTE("align"); -} +const std::string XHTML_RELATIVE_LINE_HEIGHT_ATTRIBUTE("rel-line-height"); +} // namespace void ProcessHorizontalAlignment(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun) { @@ -43,6 +44,12 @@ void ProcessHorizontalAlignment(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun.horizontalAlignment); } +void ProcessRelativeLineHeight(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun) +{ + boundedParagraphRun.relativeLineSize = StringToFloat(attribute.valueBuffer); + boundedParagraphRun.relativeLineSizeDefined = true; +} + void ProcessAttributesOfParagraphTag(const Tag& tag, BoundedParagraphRun& boundedParagraphRun) { // By default the align attribute is not defined until it's parsed. @@ -58,9 +65,12 @@ void ProcessAttributesOfParagraphTag(const Tag& tag, BoundedParagraphRun& bounde { ProcessHorizontalAlignment(attribute, boundedParagraphRun); } + else if(TokenComparison(XHTML_RELATIVE_LINE_HEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + ProcessRelativeLineHeight(attribute, boundedParagraphRun); + } } } - } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/markup-processor-paragraph.h b/dali-toolkit/internal/text/markup-processor-paragraph.h index 484b3a5..2859794 100644 --- a/dali-toolkit/internal/text/markup-processor-paragraph.h +++ b/dali-toolkit/internal/text/markup-processor-paragraph.h @@ -44,6 +44,14 @@ void ProcessHorizontalAlignment(const Attribute& attribute, BoundedParagraphRun& */ void ProcessAttributesOfParagraphTag(const Tag& tag, BoundedParagraphRun& boundedParagraphRun); +/** + * @brief Retrieves the relative line height value from the paragraph tag and sets it to the bounded paragraph run. + * + * @param[in] attribute the relative line height attribute. + * @param[in,out] boundedParagraphRun The bounded paragraph run. + */ +void ProcessRelativeLineHeight(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun); + } // namespace Text } // namespace Toolkit -- 2.7.4