/*
- * 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.
#include <dali-toolkit/internal/text/bidirectional-support.h>
#include <dali-toolkit/internal/text/cursor-helper-functions.h>
#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/layouts/layout-engine-helper-functions.h>
#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
namespace Dali
{
{
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
{
namespace
Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_LAYOUT");
#endif
-const float MAX_FLOAT = std::numeric_limits<float>::max();
-const CharacterDirection LTR = false;
-const CharacterDirection RTL = !LTR;
-const float LINE_SPACING = 0.f;
-const float MIN_LINE_SIZE = 0.f;
-const Character HYPHEN_UNICODE = 0x002D;
+const float MAX_FLOAT = std::numeric_limits<float>::max();
+const CharacterDirection LTR = false;
+const CharacterDirection RTL = !LTR;
+const float LINE_SPACING = 0.f;
+const float MIN_LINE_SIZE = 0.f;
+const Character HYPHEN_UNICODE = 0x002D;
+const float RELATIVE_LINE_SIZE = 1.f;
inline bool isEmptyLineAtLast(const Vector<LineRun>& lines, const Vector<LineRun>::Iterator& line)
{
glyphIndexInSecondHalfLine{0u},
characterIndexInSecondHalfLine{0u},
numberOfGlyphsInSecondHalfLine{0u},
- numberOfCharactersInSecondHalfLine{0u}
+ numberOfCharactersInSecondHalfLine{0u},
+ relativeLineSize{1.0f}
{
}
characterIndexInSecondHalfLine = 0u;
numberOfGlyphsInSecondHalfLine = 0u;
numberOfCharactersInSecondHalfLine = 0u;
+ relativeLineSize = 1.0f;
}
GlyphIndex glyphIndex; ///< Index of the first glyph to be laid-out.
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
: mLayout{Layout::Engine::SINGLE_LINE_BOX},
mCursorWidth{0.f},
mDefaultLineSpacing{LINE_SPACING},
- mDefaultLineSize{MIN_LINE_SIZE}
+ mDefaultLineSize{MIN_LINE_SIZE},
+ mRelativeLineSize{RELATIVE_LINE_SIZE}
+ {
+ }
+
+ /**
+ * @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 relativeLineSize)
{
+ float lineSpacing;
+ float relTextSize;
+
+ // Sets the line size
+ lineSpacing = mDefaultLineSize - textSize;
+ lineSpacing = lineSpacing < 0.f ? 0.f : lineSpacing;
+
+ // Add the line spacing
+ lineSpacing += mDefaultLineSpacing;
+
+ //subtract line spcaing if relativeLineSize < 1 & larger than min height
+ relTextSize = textSize * relativeLineSize;
+ if(relTextSize > mDefaultLineSize)
+ {
+ if(relativeLineSize < 1)
+ {
+ //subtract the difference (always will be positive)
+ lineSpacing -= (textSize - relTextSize);
+ }
+ else
+ {
+ //reverse the addition in the top.
+ if(mDefaultLineSize > textSize)
+ {
+ lineSpacing -= mDefaultLineSize - textSize;
+ }
+
+ //add difference instead
+ lineSpacing += relTextSize - textSize;
+ }
+ }
+
+ return lineSpacing;
}
/**
// Sets the minimum descender.
lineLayout.descender = std::min(lineLayout.descender, fontMetrics.descender);
- // Sets the line size
- lineLayout.lineSpacing = mDefaultLineSize - (lineLayout.ascender + -lineLayout.descender);
- lineLayout.lineSpacing = lineLayout.lineSpacing < 0.f ? 0.f : lineLayout.lineSpacing;
-
- // Add the line spacing
- lineLayout.lineSpacing += mDefaultLineSpacing;
+ lineLayout.lineSpacing = GetLineSpacing(lineLayout.ascender + -lineLayout.descender, lineLayout.relativeLineSize);
}
/**
const float outlineWidth = static_cast<float>(parameters.textModel->GetOutlineWidth());
const GlyphIndex lastGlyphOfParagraphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs;
+ const float modelCharacterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing();
+
+ // Get the character-spacing runs.
+ const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = parameters.textModel->mVisualModel->GetCharacterSpacingGlyphRuns();
CharacterIndex characterLogicalIndex = 0u;
CharacterIndex characterVisualIndex = 0u;
+ float calculatedAdvance = 0.f;
+
// If there are characters in the second half of Line then the first visual index mapped from visualToLogicalMapSecondHalf
// Otherwise maps the first visual index from visualToLogicalMap.
// This is to initialize the first visual index.
{
const GlyphInfo& glyphInfo = *(glyphsBuffer + *(charactersToGlyphsBuffer + characterVisualIndex));
- whiteSpaceLengthEndOfLine += glyphInfo.advance;
+ const float characterSpacing = GetGlyphCharacterSpacing(characterVisualIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance);
+ whiteSpaceLengthEndOfLine += calculatedAdvance;
++characterLogicalIndex;
characterVisualIndex = bidirectionalLineInfo.characterRunForSecondHalfLine.characterIndex + *(bidirectionalLineInfo.visualToLogicalMapSecondHalf + characterLogicalIndex);
{
const GlyphInfo& glyphInfo = *(glyphsBuffer + *(charactersToGlyphsBuffer + characterVisualIndex));
- whiteSpaceLengthEndOfLine += glyphInfo.advance;
+ const float characterSpacing = GetGlyphCharacterSpacing(characterVisualIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance);
+ whiteSpaceLengthEndOfLine += calculatedAdvance;
++characterLogicalIndex;
characterVisualIndex = bidirectionalLineInfo.characterRun.characterIndex + *(bidirectionalLineInfo.visualToLogicalMap + characterLogicalIndex);
charactersPerGlyphBuffer);
GlyphMetrics glyphMetrics;
+ const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
GetGlyphsMetrics(glyphIndex,
numberOfGLyphsInGroup,
glyphMetrics,
glyphsBuffer,
- mMetrics);
+ mMetrics,
+ calculatedAdvance);
float penX = -glyphMetrics.xBearing + mCursorWidth + outlineWidth;
characterLogicalIndex += *(charactersPerGlyphBuffer + glyphIndex + numberOfGLyphsInGroup - 1u);
GlyphMetrics glyphMetrics;
+ const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
GetGlyphsMetrics(glyphIndex,
numberOfGLyphsInGroup,
glyphMetrics,
glyphsBuffer,
- mMetrics);
+ mMetrics,
+ calculatedAdvance);
if(isWhiteSpace)
{
characterLogicalIndex += *(charactersPerGlyphBuffer + glyphIndex + numberOfGLyphsInGroup - 1u);
GlyphMetrics glyphMetrics;
+ const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
GetGlyphsMetrics(glyphIndex,
numberOfGLyphsInGroup,
glyphMetrics,
glyphsBuffer,
- mMetrics);
+ mMetrics,
+ calculatedAdvance);
if(isWhiteSpace)
{
* @param[out] lineLayout The line layout.
* @param[in] completelyFill Whether to completely fill the line ( even if the last word exceeds the boundaries ).
* @param[in] ellipsisPosition Where is the location the text elide
+ * @param[in] hiddenInputEnabled Whether the hidden input is enabled.
*/
void GetLineLayoutForBox(const Parameters& parameters,
LayoutBidiParameters& bidiParameters,
bool completelyFill,
DevelText::EllipsisPosition::Type ellipsisPosition,
bool enforceEllipsisInSingleLine,
- bool elideTextEnabled)
+ bool elideTextEnabled,
+ bool hiddenInputEnabled)
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->GetLineLayoutForBox\n");
DALI_LOG_INFO(gLogFilter, Debug::Verbose, " initial glyph index : %d\n", lineLayout.glyphIndex);
float widthFirstHalf = ((ellipsisPosition != DevelText::EllipsisPosition::MIDDLE) ? targetWidth : targetWidth - std::floor(targetWidth / 2));
bool isSecondHalf = false;
+ // Character Spacing
+ const float modelCharacterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing();
+ float calculatedAdvance = 0.f;
+ Vector<CharacterIndex>& glyphToCharacterMap = parameters.textModel->mVisualModel->mGlyphsToCharacters;
+ const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
+
+ // Get the character-spacing runs.
+ const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = parameters.textModel->mVisualModel->GetCharacterSpacingGlyphRuns();
GlyphMetrics glyphMetrics;
+ const float characterSpacing = GetGlyphCharacterSpacing(lineLayout.glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + lineLayout.glyphIndex))), characterSpacing, (*(glyphsBuffer + lineLayout.glyphIndex)).advance);
GetGlyphsMetrics(lineLayout.glyphIndex,
numberOfGLyphsInGroup,
glyphMetrics,
glyphsBuffer,
- mMetrics);
+ mMetrics,
+ calculatedAdvance);
// Set the direction of the first character of the line.
lineLayout.characterIndex = *(glyphsToCharactersBuffer + lineLayout.glyphIndex);
// 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);
charactersPerGlyphBuffer);
GlyphMetrics glyphMetrics;
+ const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
GetGlyphsMetrics(glyphIndex,
numberOfGLyphsInGroup,
glyphMetrics,
glyphsBuffer,
- mMetrics);
+ mMetrics,
+ calculatedAdvance);
const bool isLastGlyph = glyphIndex + numberOfGLyphsInGroup == totalNumberOfGlyphs;
const float previousTmpLength = tmpLineLayout.length;
const float previousTmpWhiteSpaceLengthEndOfLine = tmpLineLayout.whiteSpaceLengthEndOfLine;
- if(isWhiteSpace)
+ // The calculated text size is used in atlas renderer.
+ // When the text is all white space, partial render issue occurs because the width is 0.
+ // To avoid issue, do not remove the white space size in hidden input mode.
+ if(isWhiteSpace && !hiddenInputEnabled)
{
// Add the length to the length of white spaces at the end of the line.
- tmpLineLayout.whiteSpaceLengthEndOfLine += glyphMetrics.advance; // The advance is used as the width is always zero for the white spaces.
+ tmpLineLayout.whiteSpaceLengthEndOfLine += glyphMetrics.advance;
+ // The advance is used as the width is always zero for the white spaces.
}
else
{
while(tmpLineLayout.length + tmpLineLayout.whiteSpaceLengthEndOfLine > targetWidth && glyphIndexToRemove < glyphIndex)
{
GlyphMetrics glyphMetrics;
+ const float characterSpacing = GetGlyphCharacterSpacing(glyphIndexToRemove, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndexToRemove))), characterSpacing, (*(glyphsBuffer + glyphIndexToRemove)).advance);
GetGlyphsMetrics(glyphIndexToRemove,
numberOfGLyphsInGroup,
glyphMetrics,
glyphsBuffer,
- mMetrics);
+ mMetrics,
+ calculatedAdvance);
const Length numberOfGLyphsInGroup = GetNumberOfGlyphsOfGroup(glyphIndexToRemove,
lastGlyphOfParagraphPlusOne,
tmpLineLayout.numberOfGlyphs -= numberOfGLyphsInGroup;
}
- if(isRemovedGlyphWhiteSpace)
+ if(isRemovedGlyphWhiteSpace && !hiddenInputEnabled)
{
tmpLineLayout.penX -= glyphMetrics.advance;
tmpLineLayout.length -= glyphMetrics.advance;
const GlyphInfo& glyph = *(glyphsBuffer + startIndexForGlyph);
float penX = -glyph.xBearing + mCursorWidth + outlineWidth; //
- for(GlyphIndex i = 0u; i < numberOfGlyphs; ++i)
- {
- const GlyphInfo& glyph = *(glyphsBuffer + startIndexForGlyph + i);
- Vector2& position = *(glyphPositionsBuffer + startIndexForGlyphPositions + i);
-
- position.x = penX + glyph.xBearing;
- position.y = -glyph.yBearing;
-
- penX += (glyph.advance + interGlyphExtraAdvance);
- }
+ CalculateGlyphPositionsLTR(layoutParameters.textModel->mVisualModel,
+ layoutParameters.textModel->mLogicalModel,
+ interGlyphExtraAdvance,
+ numberOfGlyphs,
+ startIndexForGlyph, // startIndexForGlyph is the index of the first glyph in the line
+ startIndexForGlyphPositions,
+ glyphPositionsBuffer,
+ penX);
if(layout.isSplitToTwoHalves)
{
const Length numberOfGlyphsInSecondHalfLine = layout.numberOfGlyphsInSecondHalfLine;
const GlyphIndex startIndexForGlyphPositionsnSecondHalf = layout.glyphIndexInSecondHalfLine - layoutParameters.startGlyphIndex;
- for(GlyphIndex i = 0u; i < numberOfGlyphsInSecondHalfLine; ++i)
- {
- const GlyphInfo& glyph = *(glyphsBuffer + startIndexForGlyphInSecondHalf + i);
- Vector2& position = *(glyphPositionsBuffer + startIndexForGlyphPositionsnSecondHalf + i);
-
- position.x = penX + glyph.xBearing;
- position.y = -glyph.yBearing;
-
- penX += (glyph.advance + interGlyphExtraAdvance);
- }
+ CalculateGlyphPositionsLTR(layoutParameters.textModel->mVisualModel,
+ layoutParameters.textModel->mLogicalModel,
+ interGlyphExtraAdvance,
+ numberOfGlyphsInSecondHalfLine,
+ startIndexForGlyphInSecondHalf, // startIndexForGlyph is the index of the first glyph in the line
+ startIndexForGlyphPositionsnSecondHalf,
+ glyphPositionsBuffer,
+ penX);
}
}
LayoutBidiParameters& layoutBidiParameters,
const LineLayout& layout)
{
- const Character* const textBuffer = layoutParameters.textModel->mLogicalModel->mText.Begin();
const BidirectionalLineInfoRun& bidiLine = layoutParameters.textModel->mLogicalModel->mBidirectionalLineInfo[layoutBidiParameters.bidiLineIndex];
const GlyphInfo* const glyphsBuffer = layoutParameters.textModel->mVisualModel->mGlyphs.Begin();
const GlyphIndex* const charactersToGlyphsBuffer = layoutParameters.textModel->mVisualModel->mCharactersToGlyph.Begin();
- const Length* const glyphsPerCharacterBuffer = layoutParameters.textModel->mVisualModel->mGlyphsPerCharacter.Begin();
CharacterIndex characterLogicalIndex = 0u;
CharacterIndex characterVisualIndex = bidiLine.characterRunForSecondHalfLine.characterIndex + *(bidiLine.visualToLogicalMapSecondHalf + characterLogicalIndex);
if(layout.isSplitToTwoHalves)
{
- while(TextAbstraction::IsWhiteSpace(*(textBuffer + characterVisualIndex)))
- {
- const GlyphIndex glyphIndex = *(charactersToGlyphsBuffer + characterVisualIndex);
- const GlyphInfo& glyph = *(glyphsBuffer + glyphIndex);
-
- Vector2& position = *(glyphPositionsBuffer + glyphIndex - layoutParameters.startGlyphIndex);
- position.x = penX;
- position.y = -glyph.yBearing;
-
- penX += glyph.advance;
-
- ++characterLogicalIndex;
- characterVisualIndex = bidiLine.characterRun.characterIndex + *(bidiLine.visualToLogicalMap + characterLogicalIndex);
- }
+ CalculateGlyphPositionsRTL(layoutParameters.textModel->mVisualModel,
+ layoutParameters.textModel->mLogicalModel,
+ layoutBidiParameters.bidiLineIndex,
+ layoutParameters.startGlyphIndex,
+ glyphPositionsBuffer,
+ characterVisualIndex,
+ characterLogicalIndex,
+ penX);
}
if(characterLogicalIndex == bidiLine.characterRunForSecondHalfLine.numberOfCharacters)
characterLogicalIndex = 0u;
characterVisualIndex = bidiLine.characterRun.characterIndex + *(bidiLine.visualToLogicalMap + characterLogicalIndex);
- while(TextAbstraction::IsWhiteSpace(*(textBuffer + characterVisualIndex)))
- {
- const GlyphIndex glyphIndex = *(charactersToGlyphsBuffer + characterVisualIndex);
- const GlyphInfo& glyph = *(glyphsBuffer + glyphIndex);
-
- Vector2& position = *(glyphPositionsBuffer + glyphIndex - layoutParameters.startGlyphIndex);
- position.x = penX;
- position.y = -glyph.yBearing;
-
- penX += glyph.advance;
-
- ++characterLogicalIndex;
- characterVisualIndex = bidiLine.characterRun.characterIndex + *(bidiLine.visualToLogicalMap + characterLogicalIndex);
- }
+ CalculateGlyphPositionsRTL(layoutParameters.textModel->mVisualModel,
+ layoutParameters.textModel->mLogicalModel,
+ layoutBidiParameters.bidiLineIndex,
+ layoutParameters.startGlyphIndex,
+ glyphPositionsBuffer,
+ characterVisualIndex,
+ characterLogicalIndex,
+ penX);
}
const GlyphIndex glyphIndex = *(charactersToGlyphsBuffer + characterVisualIndex);
// Traverses the characters of the right to left paragraph.
if(layout.isSplitToTwoHalves && !extendedToSecondHalf)
{
- for(; characterLogicalIndex < bidiLine.characterRunForSecondHalfLine.numberOfCharacters;
- ++characterLogicalIndex)
- {
- // Convert the character in the logical order into the character in the visual order.
- const CharacterIndex characterVisualIndex = bidiLine.characterRunForSecondHalfLine.characterIndex + *(bidiLine.visualToLogicalMapSecondHalf + characterLogicalIndex);
-
- // Get the number of glyphs of the character.
- const Length numberOfGlyphs = *(glyphsPerCharacterBuffer + characterVisualIndex);
-
- for(GlyphIndex index = 0u; index < numberOfGlyphs; ++index)
- {
- // Convert the character in the visual order into the glyph in the visual order.
- const GlyphIndex glyphIndex = *(charactersToGlyphsBuffer + characterVisualIndex) + index;
-
- DALI_ASSERT_DEBUG(glyphIndex < layoutParameters.textModel->mVisualModel->mGlyphs.Count());
-
- const GlyphInfo& glyph = *(glyphsBuffer + glyphIndex);
- Vector2& position = *(glyphPositionsBuffer + glyphIndex - layoutParameters.startGlyphIndex);
-
- position.x = penX + glyph.xBearing;
- position.y = -glyph.yBearing;
-
- penX += (glyph.advance + layoutParameters.interGlyphExtraAdvance);
- }
- }
+ TraversesCharactersForGlyphPositionsRTL(layoutParameters.textModel->mVisualModel,
+ layoutParameters.textModel->mLogicalModel->mText.Begin(),
+ layoutParameters.startGlyphIndex,
+ layoutParameters.interGlyphExtraAdvance,
+ bidiLine.characterRunForSecondHalfLine,
+ bidiLine.visualToLogicalMapSecondHalf,
+ glyphPositionsBuffer,
+ characterLogicalIndex,
+ penX);
}
characterLogicalIndex = extendedToSecondHalf ? characterLogicalIndex : 0u;
- for(; characterLogicalIndex < bidiLine.characterRun.numberOfCharacters;
- ++characterLogicalIndex)
- {
- // Convert the character in the logical order into the character in the visual order.
- const CharacterIndex characterVisualIndex = bidiLine.characterRun.characterIndex + *(bidiLine.visualToLogicalMap + characterLogicalIndex);
-
- // Get the number of glyphs of the character.
- const Length numberOfGlyphs = *(glyphsPerCharacterBuffer + characterVisualIndex);
-
- for(GlyphIndex index = 0u; index < numberOfGlyphs; ++index)
- {
- // Convert the character in the visual order into the glyph in the visual order.
- const GlyphIndex glyphIndex = *(charactersToGlyphsBuffer + characterVisualIndex) + index;
-
- DALI_ASSERT_DEBUG(glyphIndex < layoutParameters.textModel->mVisualModel->mGlyphs.Count());
- const GlyphInfo& glyph = *(glyphsBuffer + glyphIndex);
- Vector2& position = *(glyphPositionsBuffer + glyphIndex - layoutParameters.startGlyphIndex);
-
- position.x = penX + glyph.xBearing;
- position.y = -glyph.yBearing;
-
- penX += (glyph.advance + layoutParameters.interGlyphExtraAdvance);
- }
- }
+ TraversesCharactersForGlyphPositionsRTL(layoutParameters.textModel->mVisualModel,
+ layoutParameters.textModel->mLogicalModel->mText.Begin(),
+ layoutParameters.startGlyphIndex,
+ layoutParameters.interGlyphExtraAdvance,
+ bidiLine.characterRun,
+ bidiLine.visualToLogicalMap,
+ glyphPositionsBuffer,
+ characterLogicalIndex,
+ penX);
}
/**
* @param[in] penY The vertical layout position.
* @param[in] currentParagraphDirection The current paragraph's direction.
* @param[in,out] isAutoScrollEnabled If the isAutoScrollEnabled is true and the height of the text exceeds the boundaries of the control the text is elided and the isAutoScrollEnabled is set to false to disable the autoscroll
+ * @param[in] isHiddenInputEnabled Whether the hidden input is enabled.
* @param[in] ellipsisPosition Where is the location the text elide
*
* return Whether the line is ellipsized.
Length& numberOfLines,
float penY,
bool& isAutoScrollEnabled,
+ bool isAutoScrollMaxTextureExceeded,
+ bool isHiddenInputEnabled,
DevelText::EllipsisPosition::Type ellipsisPosition,
bool enforceEllipsisInSingleLine)
{
- const bool ellipsis = enforceEllipsisInSingleLine || (isAutoScrollEnabled ? (penY - layout.descender > layoutParameters.boundingBox.height) : ((penY - layout.descender > layoutParameters.boundingBox.height) || ((mLayout == SINGLE_LINE_BOX) && (layout.length > layoutParameters.boundingBox.width))));
+ const bool ellipsis = enforceEllipsisInSingleLine || (isAutoScrollEnabled ? isAutoScrollMaxTextureExceeded : ((penY - layout.descender > layoutParameters.boundingBox.height) || ((mLayout == SINGLE_LINE_BOX) && (layout.length > layoutParameters.boundingBox.width))));
const bool isMultiline = !enforceEllipsisInSingleLine && (mLayout == MULTI_LINE_BOX);
if(ellipsis && (ellipsisPosition == DevelText::EllipsisPosition::END || !isMultiline))
{
- isAutoScrollEnabled = false;
- // Do not layout more lines if ellipsis is enabled.
+ if(penY - layout.descender > layoutParameters.boundingBox.height)
+ {
+ // Even if auto scroll is enabled and text is bigger than max texture size,
+ // if the the height is small, auto scroll should not work.
+ isAutoScrollEnabled = false;
+ }
+ // Do not layout more lines if ellipsis is enabled.
// The last line needs to be completely filled with characters.
// Part of a word may be used.
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.
true,
ellipsisPosition,
enforceEllipsisInSingleLine,
- true);
+ true,
+ isHiddenInputEnabled);
if(ellipsisPosition == DevelText::EllipsisPosition::START && !isMultiline)
{
layoutSize.width = layoutParameters.boundingBox.width;
if(layoutSize.height < Math::MACHINE_EPSILON_1000)
{
- layoutSize.height += GetLineHeight(*lineRun);
+ layoutSize.height += GetLineHeight(*lineRun, true);
+ }
+ else
+ {
+ //when we apply ellipsis, the last line should not take negative linespacing into account for layoutSize.height calculation
+ //usually we don't includ it in normal cases using GetLineHeight()
+ if(lineRun->lineSpacing < 0)
+ {
+ layoutSize.height -= lineRun->lineSpacing;
+ }
}
const Vector<BidirectionalLineInfoRun>& bidirectionalLinesInfo = layoutParameters.textModel->mLogicalModel->mBidirectionalLineInfo;
lineRun.direction = layout.direction;
lineRun.ellipsis = false;
- lineRun.lineSpacing = mDefaultLineSize - (lineRun.ascender + -lineRun.descender);
- lineRun.lineSpacing = lineRun.lineSpacing < 0.f ? 0.f : lineRun.lineSpacing;
-
- lineRun.lineSpacing += mDefaultLineSpacing;
+ lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender, layout.relativeLineSize);
// Update the actual size.
if(lineRun.width > layoutSize.width)
layoutSize.width = lineRun.width;
}
- layoutSize.height += GetLineHeight(lineRun);
+ layoutSize.height += GetLineHeight(lineRun, isLastLine);
}
/**
lineRun.direction = LTR;
lineRun.ellipsis = false;
- lineRun.lineSpacing = mDefaultLineSize - (lineRun.ascender + -lineRun.descender);
- lineRun.lineSpacing = lineRun.lineSpacing < 0.f ? 0.f : lineRun.lineSpacing;
+ BoundedParagraphRun currentParagraphRun;
+ LineLayout tempLineLayout;
+ (GetBoundedParagraph(layoutParameters.textModel->GetBoundedParagraphRuns(), characterIndex, currentParagraphRun) ? SetRelativeLineSize(¤tParagraphRun, tempLineLayout) : SetRelativeLineSize(nullptr, tempLineLayout));
- lineRun.lineSpacing += mDefaultLineSpacing;
+ lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender, tempLineLayout.relativeLineSize);
- layoutSize.height += GetLineHeight(lineRun);
+ layoutSize.height += GetLineHeight(lineRun, true);
}
/**
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);
}
}
}
}
+ /**
+ * @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<BoundedParagraphRun> boundedParagraphRuns, CharacterIndex characterIndex, BoundedParagraphRun& currentParagraphRun)
+ {
+ for(Vector<BoundedParagraphRun>::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,
bool& isAutoScrollEnabled,
+ bool isAutoScrollMaxTextureExceeded,
+ bool isHiddenInputEnabled,
DevelText::EllipsisPosition::Type ellipsisPosition)
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->LayoutText\n");
layoutParameters.textModel->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(0u);
layoutParameters.textModel->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(0u);
- Vector<LineRun>& lines = layoutParameters.textModel->mVisualModel->mLines;
+ Vector<LineRun>& lines = layoutParameters.textModel->mVisualModel->mLines;
+ const Vector<BoundedParagraphRun>& boundedParagraphRuns = layoutParameters.textModel->GetBoundedParagraphRuns();
if(0u == layoutParameters.numberOfGlyphs)
{
// 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<BidirectionalParagraphInfoRun>& bidirectionalParagraphsInfo = layoutParameters.textModel->mLogicalModel->mBidirectionalParagraphInfo;
const Vector<BidirectionalLineInfoRun>& bidirectionalLinesInfo = layoutParameters.textModel->mLogicalModel->mBidirectionalLineInfo;
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,
false,
ellipsisPosition,
false,
- elideTextEnabled);
+ elideTextEnabled,
+ isHiddenInputEnabled);
DALI_LOG_INFO(gLogFilter, Debug::Verbose, " glyph index %d\n", layout.glyphIndex);
DALI_LOG_INFO(gLogFilter, Debug::Verbose, " character index %d\n", layout.characterIndex);
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.
numberOfLines,
penY,
isAutoScrollEnabled,
+ isAutoScrollMaxTextureExceeded,
+ isHiddenInputEnabled,
ellipsisPosition,
false);
}
numberOfLines,
penY,
isAutoScrollEnabled,
+ isAutoScrollMaxTextureExceeded,
+ isHiddenInputEnabled,
ellipsisPosition,
true);
}
}
// Updates the vertical pen's position.
- penY += -layout.descender + layout.lineSpacing + mDefaultLineSpacing;
- // If there is a defaultLineSize, updates the pen's position.
- if(mDefaultLineSize > 0.f)
- {
- float lineSpacing = mDefaultLineSize - (layout.ascender + -layout.descender);
- lineSpacing = lineSpacing < 0.f ? 0.f : lineSpacing;
- penY += lineSpacing;
- }
+ penY += -layout.descender + layout.lineSpacing + GetLineSpacing(layout.ascender + -layout.descender, layout.relativeLineSize);
// Increase the glyph index.
index = nextIndex;
float mDefaultLineSize;
IntrusivePtr<Metrics> mMetrics;
+ float mRelativeLineSize;
};
Engine::Engine()
Size& layoutSize,
bool elideTextEnabled,
bool& isAutoScrollEnabled,
+ bool isAutoScrollMaxTextureExceeded,
+ bool isHiddenInputEnabled,
DevelText::EllipsisPosition::Type ellipsisPosition)
{
return mImpl->LayoutText(layoutParameters,
layoutSize,
elideTextEnabled,
isAutoScrollEnabled,
+ isAutoScrollMaxTextureExceeded,
+ isHiddenInputEnabled,
ellipsisPosition);
}
return mImpl->mDefaultLineSize;
}
+void Engine::SetRelativeLineSize(float relativeLineSize)
+{
+ mImpl->mRelativeLineSize = relativeLineSize;
+}
+
+float Engine::GetRelativeLineSize() const
+{
+ return mImpl->mRelativeLineSize;
+}
+
} // namespace Layout
} // namespace Text