X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Ftext-view.cpp;h=9c067de9e4e0baec81706dc79f3341e0eb9b16b1;hp=843992721b40620411e7496dad4b3f8c580edd1f;hb=cd5b6f3ff9138207df66d93e95a750fa9f56c70b;hpb=646440beeb663fc5efcccadeba73dd46016ed1b3 diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index 8439927..9c067de 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.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. @@ -21,6 +21,11 @@ // EXTERNAL INCLUDES #include #include +#include + +// INTERNAL INCLUDES +#include +#include namespace Dali { @@ -31,6 +36,7 @@ namespace Text struct View::Impl { VisualModelPtr mVisualModel; + LogicalModelPtr mLogicalModel; TextAbstraction::FontClient mFontClient; ///< Handle to the font client. }; @@ -52,6 +58,11 @@ void View::SetVisualModel(VisualModelPtr visualModel) mImpl->mVisualModel = visualModel; } +void View::SetLogicalModel(LogicalModelPtr logicalModel) +{ + mImpl->mLogicalModel = logicalModel; +} + const Vector2& View::GetControlSize() const { if(mImpl->mVisualModel) @@ -95,30 +106,85 @@ Length View::GetGlyphs(GlyphInfo* glyphs, GlyphIndex glyphIndex, Length numberOfGlyphs) const { - Length numberOfLaidOutGlyphs = 0u; + Length numberOfLaidOutGlyphs = 0u; + Length numberOfActualLaidOutGlyphs = 0u; + const float modelCharacterSpacing = mImpl->mVisualModel->GetCharacterSpacing(); + Vector& glyphToCharacterMap = mImpl->mVisualModel->mGlyphsToCharacters; + const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); + float calculatedAdvance = 0.f; + const Character* textBuffer = mImpl->mLogicalModel->mText.Begin(); if(mImpl->mVisualModel) { + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = mImpl->mVisualModel->GetCharacterSpacingGlyphRuns(); + + bool textElided = false; + DevelText::EllipsisPosition::Type ellipsisPosition = GetEllipsisPosition(); + + //Reset indices of ElidedGlyphs + mImpl->mVisualModel->SetStartIndexOfElidedGlyphs(0u); + mImpl->mVisualModel->SetEndIndexOfElidedGlyphs(numberOfGlyphs - 1u); // Initialization is the last index of Glyphs + mImpl->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(0u); + mImpl->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(0u); + // If ellipsis is enabled, the number of glyphs the layout engine has laid out may be less than 'numberOfGlyphs'. // Check the last laid out line to know if the layout engine elided some text. const Length numberOfLines = mImpl->mVisualModel->mLines.Count(); if(numberOfLines > 0u) { - const LineRun& lastLine = *(mImpl->mVisualModel->mLines.Begin() + (numberOfLines - 1u)); + const LineRun* const lines = mImpl->mVisualModel->mLines.Begin(); + + //Get line of ellipsis + const LineRun* ellipsisLine = nullptr; + const LineRun* ellipsisNextLine = nullptr; + bool hasEllipsis = false; + for(Length lineIndex = 0; lineIndex < numberOfLines; lineIndex++) + { + const LineRun* line = (lines + lineIndex); + if(line->ellipsis) + { + ellipsisLine = line; + hasEllipsis = true; + if(lineIndex < numberOfLines - 1u) + { + ellipsisNextLine = (lines + lineIndex + 1u); + } + break; + } + } // If ellipsis is enabled, calculate the number of laid out glyphs. // Otherwise use the given number of glyphs. - if(lastLine.ellipsis) + if(hasEllipsis) { - numberOfLaidOutGlyphs = lastLine.glyphRun.glyphIndex + lastLine.glyphRun.numberOfGlyphs; + textElided = true; + numberOfLaidOutGlyphs = numberOfGlyphs; + + if(ellipsisPosition == DevelText::EllipsisPosition::START) + { + numberOfActualLaidOutGlyphs = numberOfGlyphs - ellipsisLine->glyphRun.glyphIndex; + } + else if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE) + { + numberOfActualLaidOutGlyphs = 0u; + for(Length lineIndex = 0u; lineIndex < numberOfLines; lineIndex++) + { + numberOfActualLaidOutGlyphs += lines[lineIndex].glyphRun.numberOfGlyphs + lines[lineIndex].glyphRunSecondHalf.numberOfGlyphs; + } + } + else // DevelText::EllipsisPosition::END + { + numberOfActualLaidOutGlyphs = ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs; + } } else { - numberOfLaidOutGlyphs = numberOfGlyphs; + numberOfActualLaidOutGlyphs = numberOfLaidOutGlyphs = numberOfGlyphs; } - if(0u < numberOfLaidOutGlyphs) + if(0u < numberOfActualLaidOutGlyphs) { // Retrieve from the visual model the glyphs and positions. mImpl->mVisualModel->GetGlyphs(glyphs, @@ -131,11 +197,11 @@ Length View::GetGlyphs(GlyphInfo* glyphs, // Get the lines for the given range of glyphs. // The lines contain the alignment offset which needs to be added to the glyph's position. - LineIndex firstLine = 0u; - Length numberOfLines = 0u; + LineIndex firstLineIndex = 0u; + Length numberOfLines = 0u; mImpl->mVisualModel->GetNumberOfLines(glyphIndex, numberOfLaidOutGlyphs, - firstLine, + firstLineIndex, numberOfLines); Vector lines; @@ -147,11 +213,11 @@ Length View::GetGlyphs(GlyphInfo* glyphs, numberOfLaidOutGlyphs); // Get the first line for the given glyph range. - LineIndex lineIndex = firstLine; + LineIndex lineIndex = firstLineIndex; LineRun* line = lineBuffer + lineIndex; // Index of the last glyph of the line. - GlyphIndex lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u; + GlyphIndex lastGlyphIndexOfLine = (line->isSplitToTwoHalves ? line->glyphRunSecondHalf.glyphIndex + line->glyphRunSecondHalf.numberOfGlyphs : line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs) - 1u; // Add the alignment offset to the glyph's position. @@ -165,7 +231,7 @@ Length View::GetGlyphs(GlyphInfo* glyphs, if(lastGlyphIndexOfLine == index) { - penY += -line->descender; + penY += -line->descender + line->lineSpacing; // Get the next line. ++lineIndex; @@ -175,37 +241,76 @@ Length View::GetGlyphs(GlyphInfo* glyphs, line = lineBuffer + lineIndex; minLineOffset = std::min(minLineOffset, line->alignmentOffset); - lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u; + lastGlyphIndexOfLine = (line->isSplitToTwoHalves ? line->glyphRunSecondHalf.glyphIndex + line->glyphRunSecondHalf.numberOfGlyphs : line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs) - 1u; penY += line->ascender; } } } + // Set index where to set Ellipsis according to the selected position of Ellipsis. + // Start with this index to replace its glyph by Ellipsis, if the width is not enough, then remove more glyphs. + GlyphIndex startIndexOfEllipsis = 0u; + if(hasEllipsis) + { + if(ellipsisPosition == DevelText::EllipsisPosition::START) + { + // It's the fisrt glyph in line. + startIndexOfEllipsis = ellipsisLine->glyphRun.glyphIndex; + } + else if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE) + { + // It's the second middle of the line in case the line split to two halves. + // Otherwise it's It's the last glyph in line (line before all removed lines). + startIndexOfEllipsis = ellipsisLine->isSplitToTwoHalves ? (ellipsisLine->glyphRunSecondHalf.glyphIndex) : (ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs - 1u); + } + else // DevelText::EllipsisPosition::END + { + // It's the last glyph in line. + startIndexOfEllipsis = ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs - 1u; + } + } + if(1u == numberOfLaidOutGlyphs) { // not a point try to do ellipsis with only one laid out character. + return numberOfLaidOutGlyphs; } - if(lastLine.ellipsis) + if(textElided) { + const LineRun& elidedLine = *ellipsisLine; + if((1u == numberOfLines) && - (lastLine.ascender - lastLine.descender > 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; + + // Regardless where the location of ellipsis,in-case the hight of line is greater than control's height + // then replace the first glyph with ellipsis glyph. + // Get the first glyph which is going to be replaced and the ellipsis glyph. - GlyphInfo& glyphInfo = *glyphs; + GlyphInfo& glyphInfo = *(glyphs + indexOfFirstGlyph); const GlyphInfo& ellipsisGlyph = mImpl->mFontClient.GetEllipsisGlyph(mImpl->mFontClient.GetPointSize(glyphInfo.fontId)); // Change the 'x' and 'y' position of the ellipsis glyph. - Vector2& position = *glyphPositions; + Vector2& position = *(glyphPositions + indexOfFirstGlyph); position.x = ellipsisGlyph.xBearing; position.y = mImpl->mVisualModel->mControlSize.height - ellipsisGlyph.yBearing; // Replace the glyph by the ellipsis glyph. glyphInfo = ellipsisGlyph; - return 1u; + mImpl->mVisualModel->SetStartIndexOfElidedGlyphs(indexOfFirstGlyph); + mImpl->mVisualModel->SetEndIndexOfElidedGlyphs(indexOfFirstGlyph); + mImpl->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(indexOfFirstGlyph); + mImpl->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(indexOfFirstGlyph); + + numberOfLaidOutGlyphs = 1u; + + return numberOfLaidOutGlyphs; } // firstPenX, penY and firstPenSet are used to position the ellipsis glyph if needed. @@ -217,12 +322,16 @@ Length View::GetGlyphs(GlyphInfo* glyphs, bool inserted = false; float removedGlypsWidth = 0.f; Length numberOfRemovedGlyphs = 0u; - GlyphIndex index = numberOfLaidOutGlyphs - 1u; + GlyphIndex indexOfEllipsis = startIndexOfEllipsis; + + // Tail Mode: start by the end of line. + const bool isTailMode = ellipsisPosition == DevelText::EllipsisPosition::END || + (ellipsisPosition == DevelText::EllipsisPosition::MIDDLE && numberOfLines != 1u); // The ellipsis glyph has to fit in the place where the last glyph(s) is(are) removed. while(!inserted) { - const GlyphInfo& glyphToRemove = *(glyphs + index); + const GlyphInfo& glyphToRemove = *(glyphs + indexOfEllipsis); if(0u != glyphToRemove.fontId) { @@ -233,7 +342,7 @@ Length View::GetGlyphs(GlyphInfo* glyphs, if(!firstPenSet) { - const Vector2& position = *(glyphPositions + index); + const Vector2& position = *(glyphPositions + indexOfEllipsis); // Calculates the penY of the current line. It will be used to position the ellipsis glyph. penY = position.y + glyphToRemove.yBearing; @@ -251,14 +360,16 @@ Length View::GetGlyphs(GlyphInfo* glyphs, firstPenSet = true; } - removedGlypsWidth += std::min(glyphToRemove.advance, (glyphToRemove.xBearing + glyphToRemove.width)); + const float characterSpacing = GetGlyphCharacterSpacing(indexOfEllipsis, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + indexOfEllipsis))), characterSpacing, glyphToRemove.advance); + removedGlypsWidth += std::min(calculatedAdvance, (glyphToRemove.xBearing + glyphToRemove.width)); // Calculate the width of the ellipsis glyph and check if it fits. const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing; - if(ellipsisGlyphWidth < removedGlypsWidth) + if((ellipsisGlyphWidth < removedGlypsWidth) || (isTailMode ? (indexOfEllipsis == 0u) : (indexOfEllipsis == numberOfGlyphs - 1u))) { - GlyphInfo& glyphInfo = *(glyphs + index); - Vector2& position = *(glyphPositions + index); + GlyphInfo& glyphInfo = *(glyphs + indexOfEllipsis); + Vector2& position = *(glyphPositions + indexOfEllipsis); position.x -= (0.f > glyphInfo.xBearing) ? glyphInfo.xBearing : 0.f; // Replace the glyph by the ellipsis glyph. @@ -280,9 +391,15 @@ Length View::GetGlyphs(GlyphInfo* glyphs, if(!inserted) { - if(index > 0u) + if(isTailMode && indexOfEllipsis > 0u) { - --index; + // Tail Mode: remove glyphs from startIndexOfEllipsis then decrement indexOfEllipsis, until arrive to index zero. + --indexOfEllipsis; + } + else if(!isTailMode && indexOfEllipsis < numberOfLaidOutGlyphs - 1u) + { + // Not Tail Mode: remove glyphs from startIndexOfEllipsis then increase indexOfEllipsis, until arrive to last index (numberOfGlyphs - 1u). + ++indexOfEllipsis; } else { @@ -294,7 +411,99 @@ Length View::GetGlyphs(GlyphInfo* glyphs, } // 'Removes' all the glyphs after the ellipsis glyph. - numberOfLaidOutGlyphs -= numberOfRemovedGlyphs; + if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE) + { + //Reduce size, shift glyphs and start from ellipsis glyph + numberOfLaidOutGlyphs = numberOfActualLaidOutGlyphs - numberOfRemovedGlyphs; + + GlyphIndex firstMiddleIndexOfElidedGlyphs = 0u; + GlyphIndex secondMiddleIndexOfElidedGlyphs = 0u; + + bool isOnlySecondHalf = false; + if(isTailMode) + { + // Multi-lines case with MIDDLE + // In case the Ellipsis in the end of line, + // then this index will be the firstMiddleIndex. + // The secondMiddleIndex will be the fisrt index in next line. + // But in case there is no line after Ellipsis's line then secondMiddleIndex and endIndex equal firstMiddle + // Example: + // A: are laid out glyphs in line has Ellipsis in the end. + // N: are laid out glyphs in lines after removed lines. + // R: are removed glyphs. + // L: are removed glyphs when removed lines. + // AAAAAAAAAAAA...RRR => Here's the firstMiddleIndex (First index after last A) + // LLLLLLLLLLLLLLL + // LLLLLLLLLLLLLLL + // NNNNNNNNNNNNNN => Here's the secondMiddleIndex (First N) + // NNNNNNNNNN + + firstMiddleIndexOfElidedGlyphs = indexOfEllipsis; + if(ellipsisNextLine != nullptr) + { + secondMiddleIndexOfElidedGlyphs = ellipsisNextLine->glyphRun.glyphIndex; + } + else + { + secondMiddleIndexOfElidedGlyphs = firstMiddleIndexOfElidedGlyphs; + mImpl->mVisualModel->SetEndIndexOfElidedGlyphs(firstMiddleIndexOfElidedGlyphs); + } + } + else + { + // Single line case with MIDDLE + // In case the Ellipsis in the middle of line, + // Then the last index in first half will be firstMiddleIndex. + // And the indexOfEllipsis will be secondMiddleIndex, which is the first index in second half. + // Example: + // A: are laid out glyphs in first half of line. + // N: are laid out glyphs in second half of line. + // R: are removed glyphs. + // L: re removed glyphs when layouting text + // AAAAAAALLLLLLLLLLLRRR...NNNNN + // firstMiddleIndex (index of last A) + // secondMiddleIndex (index before first N) + + firstMiddleIndexOfElidedGlyphs = (ellipsisLine->glyphRun.numberOfGlyphs > 0u) ? (ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs - 1u) : (ellipsisLine->glyphRun.glyphIndex); + secondMiddleIndexOfElidedGlyphs = indexOfEllipsis; + isOnlySecondHalf = ellipsisLine->glyphRun.numberOfGlyphs == 0u && ellipsisLine->glyphRunSecondHalf.numberOfGlyphs > 0u; + } + + mImpl->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(firstMiddleIndexOfElidedGlyphs); + mImpl->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(secondMiddleIndexOfElidedGlyphs); + + // The number of shifted glyphs and shifting positions will be different according to Single-line or Multi-lines. + // isOnlySecondHalf will be true when MIDDLE Ellipsis glyph in single line. + if(isOnlySecondHalf) + { + Length numberOfSecondHalfGlyphs = numberOfLaidOutGlyphs - firstMiddleIndexOfElidedGlyphs; + + //Copy elided glyphs after the ellipsis glyph. + memcpy(glyphs + firstMiddleIndexOfElidedGlyphs, glyphs + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(GlyphInfo)); + memcpy(glyphPositions + firstMiddleIndexOfElidedGlyphs, glyphPositions + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(Vector2)); + } + else + { + Length numberOfSecondHalfGlyphs = numberOfLaidOutGlyphs - firstMiddleIndexOfElidedGlyphs + 1u; + + //Copy elided glyphs after the ellipsis glyph. + memcpy(glyphs + firstMiddleIndexOfElidedGlyphs + 1u, glyphs + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(GlyphInfo)); + memcpy(glyphPositions + firstMiddleIndexOfElidedGlyphs + 1u, glyphPositions + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(Vector2)); + } + } + else if(ellipsisPosition == DevelText::EllipsisPosition::START) + { + numberOfLaidOutGlyphs = numberOfActualLaidOutGlyphs - numberOfRemovedGlyphs; + //Copy elided glyphs after the ellipsis glyph. + memcpy(glyphs, glyphs + startIndexOfEllipsis + numberOfRemovedGlyphs, numberOfLaidOutGlyphs * sizeof(GlyphInfo)); + memcpy(glyphPositions, glyphPositions + startIndexOfEllipsis + numberOfRemovedGlyphs, numberOfLaidOutGlyphs * sizeof(Vector2)); + mImpl->mVisualModel->SetStartIndexOfElidedGlyphs(indexOfEllipsis); + } + else // DevelText::EllipsisPosition::END + { + numberOfLaidOutGlyphs = numberOfActualLaidOutGlyphs - numberOfRemovedGlyphs; + mImpl->mVisualModel->SetEndIndexOfElidedGlyphs(indexOfEllipsis); + } } } } @@ -436,6 +645,36 @@ float View::GetUnderlineHeight() const return 0.0f; } +Text::Underline::Type View::GetUnderlineType() const +{ + Text::Underline::Type type = Text::Underline::Type::SOLID; + if(mImpl->mVisualModel) + { + type = mImpl->mVisualModel->GetUnderlineType(); + } + return type; +} + +float View::GetDashedUnderlineWidth() const +{ + float width = 0.0f; + if(mImpl->mVisualModel) + { + width = mImpl->mVisualModel->GetDashedUnderlineWidth(); + } + return width; +} + +float View::GetDashedUnderlineGap() const +{ + float gap = 0.0f; + if(mImpl->mVisualModel) + { + gap = mImpl->mVisualModel->GetDashedUnderlineGap(); + } + return gap; +} + Length View::GetNumberOfUnderlineRuns() const { if(mImpl->mVisualModel) @@ -446,9 +685,9 @@ Length View::GetNumberOfUnderlineRuns() const return 0u; } -void View::GetUnderlineRuns(GlyphRun* underlineRuns, - UnderlineRunIndex index, - Length numberOfRuns) const +void View::GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, + UnderlineRunIndex index, + Length numberOfRuns) const { if(mImpl->mVisualModel) { @@ -476,6 +715,160 @@ uint16_t View::GetOutlineWidth() const return 0u; } +DevelText::EllipsisPosition::Type View::GetEllipsisPosition() const +{ + DevelText::EllipsisPosition::Type ellipsisPosition = DevelText::EllipsisPosition::END; + if(mImpl->mVisualModel) + { + const VisualModel& model = *mImpl->mVisualModel; + ellipsisPosition = model.GetEllipsisPosition(); + } + + return ellipsisPosition; +} + +bool View::IsTextElideEnabled() const +{ + bool isTextElideEnabled = false; + + if(mImpl->mVisualModel) + { + const VisualModel& model = *mImpl->mVisualModel; + isTextElideEnabled = model.IsTextElideEnabled(); + } + + return isTextElideEnabled; +} + +GlyphIndex View::GetStartIndexOfElidedGlyphs() const +{ + GlyphIndex startIndexOfElidedGlyphs = 0u; + + if(mImpl->mVisualModel) + { + const VisualModel& model = *mImpl->mVisualModel; + startIndexOfElidedGlyphs = model.GetStartIndexOfElidedGlyphs(); + } + + return startIndexOfElidedGlyphs; +} + +GlyphIndex View::GetEndIndexOfElidedGlyphs() const +{ + GlyphIndex endIndexOfElidedGlyphs = 0u; + + if(mImpl->mVisualModel) + { + const VisualModel& model = *mImpl->mVisualModel; + endIndexOfElidedGlyphs = model.GetEndIndexOfElidedGlyphs(); + } + + return endIndexOfElidedGlyphs; +} + +GlyphIndex View::GetFirstMiddleIndexOfElidedGlyphs() const +{ + GlyphIndex firstMiddleIndexOfElidedGlyphs = 0u; + + if(mImpl->mVisualModel) + { + const VisualModel& model = *mImpl->mVisualModel; + firstMiddleIndexOfElidedGlyphs = model.GetFirstMiddleIndexOfElidedGlyphs(); + } + + return firstMiddleIndexOfElidedGlyphs; +} + +GlyphIndex View::GetSecondMiddleIndexOfElidedGlyphs() const +{ + GlyphIndex secondMiddleIndexOfElidedGlyphs = 0u; + + if(mImpl->mVisualModel) + { + const VisualModel& model = *mImpl->mVisualModel; + secondMiddleIndexOfElidedGlyphs = model.GetSecondMiddleIndexOfElidedGlyphs(); + } + + return secondMiddleIndexOfElidedGlyphs; +} + +const Vector4& View::GetStrikethroughColor() const +{ + return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetStrikethroughColor() : Vector4::ZERO; +} + +bool View::IsStrikethroughEnabled() const +{ + return (mImpl->mVisualModel) ? mImpl->mVisualModel->IsStrikethroughEnabled() : false; +} + +float View::GetStrikethroughHeight() const +{ + return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetStrikethroughHeight() : 0.0f; +} + +Length View::GetNumberOfStrikethroughRuns() const +{ + if(mImpl->mVisualModel) + { + return mImpl->mVisualModel->GetNumberOfStrikethroughRuns(); + } + + return 0u; +} + +void View::GetStrikethroughRuns(StrikethroughGlyphRun* strikethroughRuns, + StrikethroughRunIndex index, + Length numberOfRuns) const +{ + if(mImpl->mVisualModel) + { + mImpl->mVisualModel->GetStrikethroughRuns(strikethroughRuns, + index, + numberOfRuns); + } +} + +Length View::GetNumberOfBoundedParagraphRuns() const +{ + if(mImpl->mLogicalModel) + { + return mImpl->mLogicalModel->GetNumberOfBoundedParagraphRuns(); + } + + return 0u; +} + +const Vector& View::GetBoundedParagraphRuns() const +{ + return mImpl->mLogicalModel->GetBoundedParagraphRuns(); +} + +Length View::GetNumberOfCharacterSpacingGlyphRuns() const +{ + return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetNumberOfCharacterSpacingGlyphRuns() : 0u; +} + +const Vector& View::GetCharacterSpacingGlyphRuns() const +{ + return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetCharacterSpacingGlyphRuns() : GetEmptyCharacterSpacingGlyphRuns(); +} + +const float View::GetCharacterSpacing() const +{ + return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetCharacterSpacing() : 0.f; +} + +const Character* View::GetTextBuffer() const +{ + return (mImpl->mVisualModel) ? mImpl->mLogicalModel->mText.Begin() : nullptr; +} + +const Vector& View::GetGlyphsToCharacters() const +{ + return mImpl->mVisualModel->GetGlyphsToCharacters(); +} + } // namespace Text } // namespace Toolkit