#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
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)
{
: 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.
+ * @return the line spacing value.
+ */
+ float GetLineSpacing(float textSize)
+ {
+ 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 * mRelativeLineSize;
+ if(relTextSize > mDefaultLineSize)
+ {
+ if(mRelativeLineSize < 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;
+ }
+
+ /**
* @brief Updates the line ascender and descender with the metrics of a new font.
*
* @param[in] glyphMetrics The metrics of the new font.
// 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);
}
/**
const float outlineWidth = static_cast<float>(parameters.textModel->GetOutlineWidth());
const GlyphIndex lastGlyphOfParagraphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs;
- const float characterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing();
+ 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;
{
const GlyphInfo& glyphInfo = *(glyphsBuffer + *(charactersToGlyphsBuffer + characterVisualIndex));
- calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance);
+ const float characterSpacing = GetGlyphCharacterSpacing(characterVisualIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance);
whiteSpaceLengthEndOfLine += calculatedAdvance;
++characterLogicalIndex;
{
const GlyphInfo& glyphInfo = *(glyphsBuffer + *(charactersToGlyphsBuffer + characterVisualIndex));
- calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance);
+ const float characterSpacing = GetGlyphCharacterSpacing(characterVisualIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance);
whiteSpaceLengthEndOfLine += calculatedAdvance;
++characterLogicalIndex;
charactersPerGlyphBuffer);
GlyphMetrics glyphMetrics;
- calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
+ const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
GetGlyphsMetrics(glyphIndex,
numberOfGLyphsInGroup,
glyphMetrics,
characterLogicalIndex += *(charactersPerGlyphBuffer + glyphIndex + numberOfGLyphsInGroup - 1u);
GlyphMetrics glyphMetrics;
- calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
+ const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
GetGlyphsMetrics(glyphIndex,
numberOfGLyphsInGroup,
glyphMetrics,
characterLogicalIndex += *(charactersPerGlyphBuffer + glyphIndex + numberOfGLyphsInGroup - 1u);
GlyphMetrics glyphMetrics;
- calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
+ const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
GetGlyphsMetrics(glyphIndex,
numberOfGLyphsInGroup,
glyphMetrics,
bool isSecondHalf = false;
// Character Spacing
- const float characterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing();
+ 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;
- calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + lineLayout.glyphIndex))), characterSpacing, (*(glyphsBuffer + lineLayout.glyphIndex)).advance);
+ const float characterSpacing = GetGlyphCharacterSpacing(lineLayout.glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + lineLayout.glyphIndex))), characterSpacing, (*(glyphsBuffer + lineLayout.glyphIndex)).advance);
GetGlyphsMetrics(lineLayout.glyphIndex,
numberOfGLyphsInGroup,
glyphMetrics,
charactersPerGlyphBuffer);
GlyphMetrics glyphMetrics;
- calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
+ const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance);
GetGlyphsMetrics(glyphIndex,
numberOfGLyphsInGroup,
glyphMetrics,
while(tmpLineLayout.length + tmpLineLayout.whiteSpaceLengthEndOfLine > targetWidth && glyphIndexToRemove < glyphIndex)
{
GlyphMetrics glyphMetrics;
- calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndexToRemove))), characterSpacing, (*(glyphsBuffer + glyphIndexToRemove)).advance);
+ const float characterSpacing = GetGlyphCharacterSpacing(glyphIndexToRemove, characterSpacingGlyphRuns, modelCharacterSpacing);
+ calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndexToRemove))), characterSpacing, (*(glyphsBuffer + glyphIndexToRemove)).advance);
GetGlyphsMetrics(glyphIndexToRemove,
numberOfGLyphsInGroup,
glyphMetrics,
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);
// 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;
-
- lineRun.lineSpacing += mDefaultLineSpacing;
+ lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender);
- 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);
}
}
}
// 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);
// Increase the glyph index.
index = nextIndex;
float mDefaultLineSize;
IntrusivePtr<Metrics> mMetrics;
+ float mRelativeLineSize;
};
Engine::Engine()
return mImpl->mDefaultLineSize;
}
+void Engine::SetRelativeLineSize(float relativeLineSize)
+{
+ mImpl->mRelativeLineSize = relativeLineSize;
+}
+
+float Engine::GetRelativeLineSize() const
+{
+ return mImpl->mRelativeLineSize;
+}
+
} // namespace Layout
} // namespace Text