From 150668a2aa35d52ebc3f6a27f55f5cd3a22fcf16 Mon Sep 17 00:00:00 2001 From: abdullah Date: Mon, 28 Feb 2022 17:50:04 +0300 Subject: [PATCH] fix issue with text size with negative line spacing Change-Id: If19a05e9b037bcf4076bc1761bab9976d652e6f3 --- .../src/dali-toolkit/utc-Dali-TextEditor.cpp | 33 +++++++++++++++++++++ .../src/dali-toolkit/utc-Dali-TextLabel.cpp | 34 ++++++++++++++++++++++ dali-toolkit/devel-api/text/text-utils-devel.cpp | 8 +++-- .../internal/text/cursor-helper-functions.cpp | 10 ++++--- .../internal/text/layouts/layout-engine.cpp | 22 +++++++++----- dali-toolkit/internal/text/line-run.h | 5 ++-- .../text/text-controller-impl-event-handler.cpp | 12 ++++++-- dali-toolkit/internal/text/text-geometry.cpp | 24 ++++++++------- dali-toolkit/internal/text/text-view.cpp | 2 +- 9 files changed, 119 insertions(+), 31 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index 0c3ab82..7c391b5 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp @@ -5788,6 +5788,39 @@ int UtcDaliTextEditorCharacterSpacing(void) END_TEST; } +int UtcDaliTextEditorTextSizeNegativeLineSpacing(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliTextEditorTextSizeNegativeLineSpacing"); + + TextEditor editor = TextEditor::New(); + + float lineSpacing = -20.f; + + editor.SetProperty(Actor::Property::SIZE, Vector2(450.0f, 300.f)); + editor.SetProperty(TextEditor::Property::POINT_SIZE, 10.f); + editor.SetProperty(DevelTextEditor::Property::LINE_SPACING, lineSpacing); + editor.SetProperty(TextEditor::Property::TEXT, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); + + application.GetScene().Add(editor); + application.SendNotification(); + application.Render(); + + Vector positionsList = DevelTextEditor::GetTextPosition(editor, 0, 123); + Vector sizeList = DevelTextEditor::GetTextSize(editor, 0, 123); + + Vector2 lastLinePos = positionsList[positionsList.Size() - 1]; + Vector2 lastLineSize = sizeList[sizeList.Size() - 1]; + + DALI_TEST_EQUALS(sizeList[0].y * (sizeList.Size() - 1), lastLinePos.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + DALI_TEST_EQUALS(sizeList[0].y - lineSpacing, lastLineSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + application.SendNotification(); + application.Render(); + + END_TEST; +} + int UtcDaliToolkitTexteditorParagraphTag(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 ecc5f67..b4d943d 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -2655,6 +2655,40 @@ int UtcDaliTextLabelCharacterSpacing(void) END_TEST; } +int UtcDaliTextTextLabelSizeNegativeLineSpacing(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliTextTextLabelSizeNegativeLineSpacing"); + + TextLabel label = TextLabel::New(); + + float lineSpacing = -20.f; + + label.SetProperty(Actor::Property::SIZE, Vector2(450.0f, 300.f)); + label.SetProperty(TextLabel::Property::POINT_SIZE, 10.f); + label.SetProperty(DevelTextLabel::Property::LINE_SPACING, lineSpacing); + label.SetProperty(TextLabel::Property::MULTI_LINE, true); + label.SetProperty(TextLabel::Property::TEXT, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); + + application.GetScene().Add(label); + application.SendNotification(); + application.Render(); + + Vector positionsList = DevelTextLabel::GetTextPosition(label, 0, 123); + Vector sizeList = DevelTextLabel::GetTextSize(label, 0, 123); + + Vector2 lastLinePos = positionsList[positionsList.Size() - 1]; + Vector2 lastLineSize = sizeList[sizeList.Size() - 1]; + + DALI_TEST_EQUALS(sizeList[0].y * (sizeList.Size() - 1), lastLinePos.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + DALI_TEST_EQUALS(sizeList[0].y - lineSpacing, lastLineSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + application.SendNotification(); + application.Render(); + + END_TEST; +} + int UtcDaliToolkitTextlabelParagraphTag(void) { ToolkitTestApplication application; diff --git a/dali-toolkit/devel-api/text/text-utils-devel.cpp b/dali-toolkit/devel-api/text/text-utils-devel.cpp index 81b82d8..7b5e36e 100644 --- a/dali-toolkit/devel-api/text/text-utils-devel.cpp +++ b/dali-toolkit/devel-api/text/text-utils-devel.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -40,7 +41,6 @@ #include #include #include -#include namespace Dali { @@ -835,7 +835,7 @@ void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRen { Length finalNumberOfGlyphs = 0u; - if((GetLineHeight(line)) > textLayoutArea.height) + if((GetLineHeight(line, (lines.Size() == 1))) > textLayoutArea.height) { // The height of the line is bigger than the height of the text area. // Show the ellipsis glyph even if it doesn't fit in the text area. @@ -1528,12 +1528,14 @@ Dali::Property::Array RenderForLastIndex(RendererParameters& textParameters) float penY = 0.f; float lineSize = internalData.layoutEngine.GetDefaultLineSize(); float lineOffset = 0.f; + bool isLastLine; for(unsigned int index = 0u; index < numberOfLines; ++index) { const LineRun& line = *(lines.Begin() + index); numberOfCharacters += line.characterRun.numberOfCharacters; + isLastLine = (index == numberOfLines - 1); - lineOffset = lineSize > 0.f ? lineSize : GetLineHeight(line); + lineOffset = lineSize > 0.f ? lineSize : GetLineHeight(line, isLastLine); penY += lineOffset; if((penY + lineOffset) > boundingBox) { diff --git a/dali-toolkit/internal/text/cursor-helper-functions.cpp b/dali-toolkit/internal/text/cursor-helper-functions.cpp index 9137a2f..3bfc059 100644 --- a/dali-toolkit/internal/text/cursor-helper-functions.cpp +++ b/dali-toolkit/internal/text/cursor-helper-functions.cpp @@ -153,9 +153,10 @@ LineIndex GetClosestLine(VisualModelPtr visualModel, it != endIt; ++it, ++lineIndex) { - const LineRun& lineRun = *it; + const LineRun& lineRun = *it; + bool isLastLine = (it + 1 == endIt); - totalHeight += GetLineHeight(lineRun); + totalHeight += GetLineHeight(lineRun, isLastLine); if(visualY < totalHeight) { @@ -182,9 +183,10 @@ float CalculateLineOffset(const Vector& lines, it != endIt; ++it) { - const LineRun& lineRun = *it; + const LineRun& lineRun = *it; + bool isLastLine = (it + 1 == lines.End()); - offset += GetLineHeight(lineRun); + offset += GetLineHeight(lineRun, isLastLine); } return offset; diff --git a/dali-toolkit/internal/text/layouts/layout-engine.cpp b/dali-toolkit/internal/text/layouts/layout-engine.cpp index c8addcc..a85f5f6 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.cpp +++ b/dali-toolkit/internal/text/layouts/layout-engine.cpp @@ -37,11 +37,18 @@ namespace Toolkit { namespace Text { -float GetLineHeight(const LineRun lineRun) +float GetLineHeight(const LineRun lineRun, bool isLastLine) { // The line height is the addition of the line ascender, the line descender and the line spacing. // However, the line descender has a negative value, hence the subtraction. - return lineRun.ascender - lineRun.descender + lineRun.lineSpacing; + // In case this is the only/last line then line spacing should be ignored. + float lineHeight = lineRun.ascender - lineRun.descender; + + if(!isLastLine || lineRun.lineSpacing > 0) + { + lineHeight += lineRun.lineSpacing; + } + return lineHeight; } namespace Layout @@ -1257,7 +1264,7 @@ struct Engine::Impl layoutSize.width = layoutParameters.boundingBox.width; if(layoutSize.height < Math::MACHINE_EPSILON_1000) { - layoutSize.height += GetLineHeight(*lineRun); + layoutSize.height += GetLineHeight(*lineRun, true); } const Vector& bidirectionalLinesInfo = layoutParameters.textModel->mLogicalModel->mBidirectionalLineInfo; @@ -1364,7 +1371,7 @@ struct Engine::Impl layoutSize.width = lineRun.width; } - layoutSize.height += GetLineHeight(lineRun); + layoutSize.height += GetLineHeight(lineRun, isLastLine); } /** @@ -1415,7 +1422,7 @@ struct Engine::Impl lineRun.lineSpacing += mDefaultLineSpacing; - layoutSize.height += GetLineHeight(lineRun); + layoutSize.height += GetLineHeight(lineRun, true); } /** @@ -1432,14 +1439,15 @@ struct Engine::Impl it != endIt; ++it) { - const LineRun& line = *it; + const LineRun& line = *it; + bool isLastLine = (it + 1 == endIt); if(line.width > layoutSize.width) { layoutSize.width = line.width; } - layoutSize.height += GetLineHeight(line); + layoutSize.height += GetLineHeight(line, isLastLine); } } diff --git a/dali-toolkit/internal/text/line-run.h b/dali-toolkit/internal/text/line-run.h index 52c47a1..c0bb095 100644 --- a/dali-toolkit/internal/text/line-run.h +++ b/dali-toolkit/internal/text/line-run.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_TEXT_LINE_RUN_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,8 +52,9 @@ struct LineRun * @brief Get the line height for the specified line run. * * @param[in] lineRun The line runs to get the height for. + * @param[in] isLastLine whether this is the last line in the text. */ -float GetLineHeight(const LineRun lineRun); +float GetLineHeight(const LineRun lineRun, bool isLastLine); } // namespace Text diff --git a/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp b/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp index 290c229..cee6a88 100644 --- a/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp +++ b/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -334,6 +334,8 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const const LineIndex lineIndex = visualModel->GetLineOfCharacter(characterIndex); const LineIndex previousLineIndex = (lineIndex > 0 ? lineIndex - 1u : lineIndex); + const LineIndex lastLineIndex = (visualModel->mLines.Size() > 0 ? visualModel->mLines.Size() - 1u : 0); + const bool isLastLine = (previousLineIndex == lastLineIndex); // Retrieve the cursor position info. CursorInfo cursorInfo; @@ -344,7 +346,7 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const const LineRun& line = *(visualModel->mLines.Begin() + previousLineIndex); // Get the next hit 'y' point. - const float hitPointY = cursorInfo.lineOffset - 0.5f * GetLineHeight(line); + const float hitPointY = cursorInfo.lineOffset - 0.5f * GetLineHeight(line, isLastLine); // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index. bool matchedCharacter = false; @@ -379,8 +381,12 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const // Get the line below. const LineRun& line = *(visualModel->mLines.Begin() + lineIndex + 1u); + // Get last line index + const LineIndex lastLineIndex = (visualModel->mLines.Size() > 0 ? visualModel->mLines.Size() - 1u : 0); + const bool isLastLine = (lineIndex + 1u == lastLineIndex); + // Get the next hit 'y' point. - const float hitPointY = cursorInfo.lineOffset + cursorInfo.lineHeight + 0.5f * GetLineHeight(line); + const float hitPointY = cursorInfo.lineOffset + cursorInfo.lineHeight + 0.5f * GetLineHeight(line, isLastLine); // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index. bool matchedCharacter = false; diff --git a/dali-toolkit/internal/text/text-geometry.cpp b/dali-toolkit/internal/text/text-geometry.cpp index 9fa5ad1..bde5517 100644 --- a/dali-toolkit/internal/text/text-geometry.cpp +++ b/dali-toolkit/internal/text/text-geometry.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,13 +32,14 @@ namespace Toolkit { namespace Text { -bool GetNextLine(GlyphIndex index, LineIndex& lineIndex, LineRun*& lineRun, GlyphIndex& lastGlyphOfLine, Length numberOfLines) +bool GetNextLine(GlyphIndex index, LineIndex& lineIndex, LineRun*& lineRun, GlyphIndex& lastGlyphOfLine, Length numberOfLines, bool& isLastLine) { if(index == lastGlyphOfLine) { ++lineIndex; if(lineIndex < numberOfLines) { + isLastLine = (lineIndex + 1 == numberOfLines); ++lineRun; return true; } @@ -47,11 +48,11 @@ bool GetNextLine(GlyphIndex index, LineIndex& lineIndex, LineRun*& lineRun, Glyp return false; } -void UpdateLineInfo(const LineRun* lineRun, float& currentLineOffset, float& currentLineHeight, GlyphIndex& lastGlyphOfLine) +void UpdateLineInfo(const LineRun* lineRun, float& currentLineOffset, float& currentLineHeight, GlyphIndex& lastGlyphOfLine, bool isLastLine) { lastGlyphOfLine = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1u; currentLineOffset = currentLineOffset + currentLineHeight; - currentLineHeight = GetLineHeight(*lineRun); + currentLineHeight = GetLineHeight(*lineRun, isLastLine); } void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterIndex endIndex, Vector& sizesList, Vector& positionsList) @@ -100,6 +101,7 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd GlyphIndex glyphEnd = *(charactersToGlyphBuffer + endIndex) + ((numberOfGlyphs > 0) ? numberOfGlyphs - 1u : 0u); LineIndex lineIndex = visualModel->GetLineOfCharacter(startIndex); Length numberOfLines = visualModel->GetTotalNumberOfLines(); + bool isLastLine = lineIndex + 1 == numberOfLines; LineIndex firstLineIndex = lineIndex; Size textInLineSize; @@ -109,7 +111,7 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd //get the first line and its vertical offset float currentLineOffset = CalculateLineOffset(visualModel->mLines, firstLineIndex); - float currentLineHeight = GetLineHeight(*lineRun); + float currentLineHeight = GetLineHeight(*lineRun, isLastLine); GlyphIndex lastGlyphOfLine = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1; // Check if the first/last glyph is a ligature that needs be splitted like English fi or Arabic ï»». @@ -148,9 +150,9 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd positionsList.PushBack(blockPos); } - if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines)) + if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines, isLastLine)) { - UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine); + UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine, isLastLine); } // Ignore any glyph that was removed continue; @@ -165,9 +167,9 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd } else if((ellipsisPosition == DevelText::EllipsisPosition::START) && (index <= startIndexOfGlyphs)) { - if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines)) + if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines, isLastLine)) { - UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine); + UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine, isLastLine); } continue; @@ -214,9 +216,9 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd currentSize.y = currentLineHeight; // if there is next line to retrieve. - if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines)) + if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines, isLastLine)) { - UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine); + UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine, isLastLine); } } diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index ed64520..fdccbe1 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -279,7 +279,7 @@ Length View::GetGlyphs(GlyphInfo* glyphs, const LineRun& elidedLine = *ellipsisLine; if((1u == numberOfLines) && - (GetLineHeight(elidedLine) > mImpl->mVisualModel->mControlSize.height)) + (GetLineHeight(elidedLine, true) > mImpl->mVisualModel->mControlSize.height)) { // Replace the first glyph with ellipsis glyph auto indexOfFirstGlyph = (ellipsisPosition == DevelText::EllipsisPosition::START) ? startIndexOfEllipsis : 0u; -- 2.7.4