2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/internal/text/text-view.h>
22 #include <dali/devel-api/text-abstraction/font-client.h>
23 #include <dali/public-api/math/vector2.h>
27 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
28 #include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
38 VisualModelPtr mVisualModel;
39 LogicalModelPtr mLogicalModel;
40 TextAbstraction::FontClient mFontClient; ///< Handle to the font client.
46 mImpl = new View::Impl();
48 mImpl->mFontClient = TextAbstraction::FontClient::Get();
56 void View::SetVisualModel(VisualModelPtr visualModel)
58 mImpl->mVisualModel = visualModel;
61 void View::SetLogicalModel(LogicalModelPtr logicalModel)
63 mImpl->mLogicalModel = logicalModel;
66 const Vector2& View::GetControlSize() const
68 if(mImpl->mVisualModel)
70 return mImpl->mVisualModel->mControlSize;
76 const Vector2& View::GetLayoutSize() const
78 if(mImpl->mVisualModel)
80 return mImpl->mVisualModel->GetLayoutSize();
86 Length View::GetNumberOfGlyphs() const
88 if(mImpl->mVisualModel)
90 const VisualModel& model = *mImpl->mVisualModel;
92 const Length glyphCount = model.mGlyphs.Count();
93 const Length positionCount = model.mGlyphPositions.Count();
95 DALI_ASSERT_DEBUG(positionCount <= glyphCount && "Invalid glyph positions in Model");
97 return (positionCount < glyphCount) ? positionCount : glyphCount;
103 Length View::GetGlyphs(GlyphInfo* glyphs,
104 Vector2* glyphPositions,
105 float& minLineOffset,
106 GlyphIndex glyphIndex,
107 Length numberOfGlyphs) const
109 Length numberOfLaidOutGlyphs = 0u;
110 Length numberOfActualLaidOutGlyphs = 0u;
111 const float modelCharacterSpacing = mImpl->mVisualModel->GetCharacterSpacing();
112 Vector<CharacterIndex>& glyphToCharacterMap = mImpl->mVisualModel->mGlyphsToCharacters;
113 const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
114 float calculatedAdvance = 0.f;
115 const Character* textBuffer = mImpl->mLogicalModel->mText.Begin();
117 if(mImpl->mVisualModel)
119 // Get the character-spacing runs.
120 const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = mImpl->mVisualModel->GetCharacterSpacingGlyphRuns();
122 bool textElided = false;
123 DevelText::EllipsisPosition::Type ellipsisPosition = GetEllipsisPosition();
125 //Reset indices of ElidedGlyphs
126 mImpl->mVisualModel->SetStartIndexOfElidedGlyphs(0u);
127 mImpl->mVisualModel->SetEndIndexOfElidedGlyphs(numberOfGlyphs - 1u); // Initialization is the last index of Glyphs
128 mImpl->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(0u);
129 mImpl->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(0u);
131 // If ellipsis is enabled, the number of glyphs the layout engine has laid out may be less than 'numberOfGlyphs'.
132 // Check the last laid out line to know if the layout engine elided some text.
134 const Length numberOfLines = mImpl->mVisualModel->mLines.Count();
135 if(numberOfLines > 0u)
137 const LineRun* const lines = mImpl->mVisualModel->mLines.Begin();
139 //Get line of ellipsis
140 const LineRun* ellipsisLine = nullptr;
141 const LineRun* ellipsisNextLine = nullptr;
142 bool hasEllipsis = false;
143 for(Length lineIndex = 0; lineIndex < numberOfLines; lineIndex++)
145 const LineRun* line = (lines + lineIndex);
150 if(lineIndex < numberOfLines - 1u)
152 ellipsisNextLine = (lines + lineIndex + 1u);
158 // If ellipsis is enabled, calculate the number of laid out glyphs.
159 // Otherwise use the given number of glyphs.
163 numberOfLaidOutGlyphs = numberOfGlyphs;
165 if(ellipsisPosition == DevelText::EllipsisPosition::START)
167 numberOfActualLaidOutGlyphs = numberOfGlyphs - ellipsisLine->glyphRun.glyphIndex;
169 else if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE)
171 numberOfActualLaidOutGlyphs = 0u;
172 for(Length lineIndex = 0u; lineIndex < numberOfLines; lineIndex++)
174 numberOfActualLaidOutGlyphs += lines[lineIndex].glyphRun.numberOfGlyphs + lines[lineIndex].glyphRunSecondHalf.numberOfGlyphs;
177 else // DevelText::EllipsisPosition::END
179 numberOfActualLaidOutGlyphs = ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs;
184 numberOfActualLaidOutGlyphs = numberOfLaidOutGlyphs = numberOfGlyphs;
187 if(0u < numberOfActualLaidOutGlyphs)
189 // Retrieve from the visual model the glyphs and positions.
190 mImpl->mVisualModel->GetGlyphs(glyphs,
192 numberOfLaidOutGlyphs);
194 mImpl->mVisualModel->GetGlyphPositions(glyphPositions,
196 numberOfLaidOutGlyphs);
198 // Get the lines for the given range of glyphs.
199 // The lines contain the alignment offset which needs to be added to the glyph's position.
200 LineIndex firstLineIndex = 0u;
201 Length numberOfLines = 0u;
202 mImpl->mVisualModel->GetNumberOfLines(glyphIndex,
203 numberOfLaidOutGlyphs,
207 Vector<LineRun> lines;
208 lines.Resize(numberOfLines);
209 LineRun* lineBuffer = lines.Begin();
211 mImpl->mVisualModel->GetLinesOfGlyphRange(lineBuffer,
213 numberOfLaidOutGlyphs);
215 // Get the first line for the given glyph range.
216 LineIndex lineIndex = firstLineIndex;
217 LineRun* line = lineBuffer + lineIndex;
219 // Index of the last glyph of the line.
220 GlyphIndex lastGlyphIndexOfLine = (line->isSplitToTwoHalves ? line->glyphRunSecondHalf.glyphIndex + line->glyphRunSecondHalf.numberOfGlyphs : line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs) - 1u;
222 // Add the alignment offset to the glyph's position.
224 minLineOffset = line->alignmentOffset;
225 float penY = line->ascender;
226 for(Length index = 0u; index < numberOfLaidOutGlyphs; ++index)
228 Vector2& position = *(glyphPositions + index);
229 position.x += line->alignmentOffset;
232 if(lastGlyphIndexOfLine == index)
234 penY += -line->descender + line->lineSpacing;
236 // Get the next line.
239 if(lineIndex < numberOfLines)
241 line = lineBuffer + lineIndex;
242 minLineOffset = std::min(minLineOffset, line->alignmentOffset);
244 lastGlyphIndexOfLine = (line->isSplitToTwoHalves ? line->glyphRunSecondHalf.glyphIndex + line->glyphRunSecondHalf.numberOfGlyphs : line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs) - 1u;
246 penY += line->ascender;
251 // Set index where to set Ellipsis according to the selected position of Ellipsis.
252 // Start with this index to replace its glyph by Ellipsis, if the width is not enough, then remove more glyphs.
253 GlyphIndex startIndexOfEllipsis = 0u;
256 if(ellipsisPosition == DevelText::EllipsisPosition::START)
258 // It's the fisrt glyph in line.
259 startIndexOfEllipsis = ellipsisLine->glyphRun.glyphIndex;
261 else if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE)
263 // It's the second middle of the line in case the line split to two halves.
264 // Otherwise it's It's the last glyph in line (line before all removed lines).
265 startIndexOfEllipsis = ellipsisLine->isSplitToTwoHalves ? (ellipsisLine->glyphRunSecondHalf.glyphIndex) : (ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs - 1u);
267 else // DevelText::EllipsisPosition::END
269 // It's the last glyph in line.
270 startIndexOfEllipsis = ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs - 1u;
274 if(1u == numberOfLaidOutGlyphs)
276 // not a point try to do ellipsis with only one laid out character.
278 return numberOfLaidOutGlyphs;
283 const LineRun& elidedLine = *ellipsisLine;
285 if((1u == numberOfLines) &&
286 (GetLineHeight(elidedLine, true) > mImpl->mVisualModel->mControlSize.height))
288 // Replace the first glyph with ellipsis glyph
289 auto indexOfFirstGlyph = (ellipsisPosition == DevelText::EllipsisPosition::START) ? startIndexOfEllipsis : 0u;
291 // Regardless where the location of ellipsis,in-case the hight of line is greater than control's height
292 // then replace the first glyph with ellipsis glyph.
294 // Get the first glyph which is going to be replaced and the ellipsis glyph.
295 GlyphInfo& glyphInfo = *(glyphs + indexOfFirstGlyph);
296 const GlyphInfo& ellipsisGlyph = mImpl->mFontClient.GetEllipsisGlyph(mImpl->mFontClient.GetPointSize(glyphInfo.fontId));
298 // Change the 'x' and 'y' position of the ellipsis glyph.
299 Vector2& position = *(glyphPositions + indexOfFirstGlyph);
300 position.x = ellipsisGlyph.xBearing;
301 position.y = mImpl->mVisualModel->mControlSize.height - ellipsisGlyph.yBearing;
303 // Replace the glyph by the ellipsis glyph.
304 glyphInfo = ellipsisGlyph;
306 mImpl->mVisualModel->SetStartIndexOfElidedGlyphs(indexOfFirstGlyph);
307 mImpl->mVisualModel->SetEndIndexOfElidedGlyphs(indexOfFirstGlyph);
308 mImpl->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(indexOfFirstGlyph);
309 mImpl->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(indexOfFirstGlyph);
311 numberOfLaidOutGlyphs = 1u;
313 return numberOfLaidOutGlyphs;
316 // firstPenX, penY and firstPenSet are used to position the ellipsis glyph if needed.
317 float firstPenX = 0.f; // Used if rtl text is elided.
319 bool firstPenSet = false;
321 // Add the ellipsis glyph.
322 bool inserted = false;
323 float removedGlypsWidth = 0.f;
324 Length numberOfRemovedGlyphs = 0u;
325 GlyphIndex indexOfEllipsis = startIndexOfEllipsis;
327 // Tail Mode: start by the end of line.
328 const bool isTailMode = ellipsisPosition == DevelText::EllipsisPosition::END ||
329 (ellipsisPosition == DevelText::EllipsisPosition::MIDDLE && numberOfLines != 1u);
331 // The ellipsis glyph has to fit in the place where the last glyph(s) is(are) removed.
334 const GlyphInfo& glyphToRemove = *(glyphs + indexOfEllipsis);
336 if(0u != glyphToRemove.fontId)
338 // i.e. The font id of the glyph shaped from the '\n' character is zero.
340 // Need to reshape the glyph as the font may be different in size.
341 const GlyphInfo& ellipsisGlyph = mImpl->mFontClient.GetEllipsisGlyph(mImpl->mFontClient.GetPointSize(glyphToRemove.fontId));
345 const Vector2& position = *(glyphPositions + indexOfEllipsis);
347 // Calculates the penY of the current line. It will be used to position the ellipsis glyph.
348 penY = position.y + glyphToRemove.yBearing;
350 // Calculates the first penX which will be used if rtl text is elided.
351 firstPenX = position.x - glyphToRemove.xBearing;
352 if(firstPenX < -ellipsisGlyph.xBearing)
354 // Avoids to exceed the bounding box when rtl text is elided.
355 firstPenX = -ellipsisGlyph.xBearing;
358 removedGlypsWidth = -ellipsisGlyph.xBearing;
363 const float characterSpacing = GetGlyphCharacterSpacing(indexOfEllipsis, characterSpacingGlyphRuns, modelCharacterSpacing);
364 calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + indexOfEllipsis))), characterSpacing, glyphToRemove.advance);
365 removedGlypsWidth += std::min(calculatedAdvance, (glyphToRemove.xBearing + glyphToRemove.width));
367 // Calculate the width of the ellipsis glyph and check if it fits.
368 const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing;
369 if((ellipsisGlyphWidth < removedGlypsWidth) || (isTailMode ? (indexOfEllipsis == 0u) : (indexOfEllipsis == numberOfGlyphs - 1u)))
371 GlyphInfo& glyphInfo = *(glyphs + indexOfEllipsis);
372 Vector2& position = *(glyphPositions + indexOfEllipsis);
373 position.x -= (0.f > glyphInfo.xBearing) ? glyphInfo.xBearing : 0.f;
375 // Replace the glyph by the ellipsis glyph.
376 glyphInfo = ellipsisGlyph;
378 // Change the 'x' and 'y' position of the ellipsis glyph.
379 if(position.x > firstPenX)
383 // To handle case of the mixed languages (LTR then RTL) with
384 // EllipsisPosition::END and the LayoutDirection::RIGHT_TO_LEFT
385 float nextXPositions = ellipsisLine->width;
386 if(indexOfEllipsis + 1u < numberOfGlyphs)
388 Vector2& positionOfNextGlyph = *(glyphPositions + indexOfEllipsis + 1u);
389 nextXPositions = positionOfNextGlyph.x;
392 if(position.x > nextXPositions) // RTL language
394 if((indexOfEllipsis > 0u) && ((position.x - nextXPositions) > removedGlypsWidth))
396 // To handle mixed directions
397 // Re-calculates the first penX which will be used if rtl text is elided.
398 firstPenX = position.x - glyphToRemove.xBearing;
399 if(firstPenX < -ellipsisGlyph.xBearing)
401 // Avoids to exceed the bounding box when rtl text is elided.
402 firstPenX = -ellipsisGlyph.xBearing;
404 //Reset the width of removed glyphs
405 removedGlypsWidth = std::min(calculatedAdvance, (glyphToRemove.xBearing + glyphToRemove.width)) - ellipsisGlyph.xBearing;
412 // To handle the case of RTL language with EllipsisPosition::END
413 position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
419 // To handle the case of LTR language with EllipsisPosition::START
420 position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
427 // To handle case of the mixed languages (RTL then LTR) with
428 // EllipsisPosition::START and the LayoutDirection::RIGHT_TO_LEFT
429 float nextXPositions = ellipsisLine->width;
430 if(indexOfEllipsis + 1u < numberOfGlyphs)
432 Vector2& positionOfNextGlyph = *(glyphPositions + indexOfEllipsis + 1u);
433 nextXPositions = positionOfNextGlyph.x;
436 if(position.x < nextXPositions) // LTR language
438 position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
440 if((position.x + ellipsisGlyphWidth + ellipsisGlyph.xBearing) > nextXPositions)
442 position.x -= (position.x + ellipsisGlyphWidth + ellipsisGlyph.xBearing) - nextXPositions;
448 position.x += ellipsisGlyph.xBearing;
449 position.y = penY - ellipsisGlyph.yBearing;
457 if(isTailMode && indexOfEllipsis > 0u)
459 // Tail Mode: remove glyphs from startIndexOfEllipsis then decrement indexOfEllipsis, until arrive to index zero.
462 else if(!isTailMode && indexOfEllipsis < numberOfLaidOutGlyphs - 1u)
464 // Not Tail Mode: remove glyphs from startIndexOfEllipsis then increase indexOfEllipsis, until arrive to last index (numberOfGlyphs - 1u).
469 // No space for the ellipsis.
472 ++numberOfRemovedGlyphs;
476 // 'Removes' all the glyphs after the ellipsis glyph.
477 if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE)
479 //Reduce size, shift glyphs and start from ellipsis glyph
480 numberOfLaidOutGlyphs = numberOfActualLaidOutGlyphs - numberOfRemovedGlyphs;
482 GlyphIndex firstMiddleIndexOfElidedGlyphs = 0u;
483 GlyphIndex secondMiddleIndexOfElidedGlyphs = 0u;
485 bool isOnlySecondHalf = false;
488 // Multi-lines case with MIDDLE
489 // In case the Ellipsis in the end of line,
490 // then this index will be the firstMiddleIndex.
491 // The secondMiddleIndex will be the fisrt index in next line.
492 // But in case there is no line after Ellipsis's line then secondMiddleIndex and endIndex equal firstMiddle
494 // A: are laid out glyphs in line has Ellipsis in the end.
495 // N: are laid out glyphs in lines after removed lines.
496 // R: are removed glyphs.
497 // L: are removed glyphs when removed lines.
498 // AAAAAAAAAAAA...RRR => Here's the firstMiddleIndex (First index after last A)
501 // NNNNNNNNNNNNNN => Here's the secondMiddleIndex (First N)
504 firstMiddleIndexOfElidedGlyphs = indexOfEllipsis;
505 if(ellipsisNextLine != nullptr)
507 secondMiddleIndexOfElidedGlyphs = ellipsisNextLine->glyphRun.glyphIndex;
511 secondMiddleIndexOfElidedGlyphs = firstMiddleIndexOfElidedGlyphs;
512 mImpl->mVisualModel->SetEndIndexOfElidedGlyphs(firstMiddleIndexOfElidedGlyphs);
517 // Single line case with MIDDLE
518 // In case the Ellipsis in the middle of line,
519 // Then the last index in first half will be firstMiddleIndex.
520 // And the indexOfEllipsis will be secondMiddleIndex, which is the first index in second half.
522 // A: are laid out glyphs in first half of line.
523 // N: are laid out glyphs in second half of line.
524 // R: are removed glyphs.
525 // L: re removed glyphs when layouting text
526 // AAAAAAALLLLLLLLLLLRRR...NNNNN
527 // firstMiddleIndex (index of last A)
528 // secondMiddleIndex (index before first N)
530 firstMiddleIndexOfElidedGlyphs = (ellipsisLine->glyphRun.numberOfGlyphs > 0u) ? (ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs - 1u) : (ellipsisLine->glyphRun.glyphIndex);
531 secondMiddleIndexOfElidedGlyphs = indexOfEllipsis;
532 isOnlySecondHalf = ellipsisLine->glyphRun.numberOfGlyphs == 0u && ellipsisLine->glyphRunSecondHalf.numberOfGlyphs > 0u;
535 mImpl->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(firstMiddleIndexOfElidedGlyphs);
536 mImpl->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(secondMiddleIndexOfElidedGlyphs);
538 // The number of shifted glyphs and shifting positions will be different according to Single-line or Multi-lines.
539 // isOnlySecondHalf will be true when MIDDLE Ellipsis glyph in single line.
542 Length numberOfSecondHalfGlyphs = numberOfLaidOutGlyphs - firstMiddleIndexOfElidedGlyphs;
544 //Copy elided glyphs after the ellipsis glyph.
545 memcpy(glyphs + firstMiddleIndexOfElidedGlyphs, glyphs + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(GlyphInfo));
546 memcpy(glyphPositions + firstMiddleIndexOfElidedGlyphs, glyphPositions + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(Vector2));
550 Length numberOfSecondHalfGlyphs = numberOfLaidOutGlyphs - firstMiddleIndexOfElidedGlyphs + 1u;
552 //Copy elided glyphs after the ellipsis glyph.
553 memcpy(glyphs + firstMiddleIndexOfElidedGlyphs + 1u, glyphs + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(GlyphInfo));
554 memcpy(glyphPositions + firstMiddleIndexOfElidedGlyphs + 1u, glyphPositions + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(Vector2));
557 else if(ellipsisPosition == DevelText::EllipsisPosition::START)
559 numberOfLaidOutGlyphs = numberOfActualLaidOutGlyphs - numberOfRemovedGlyphs;
560 //Copy elided glyphs after the ellipsis glyph.
561 memcpy(glyphs, glyphs + startIndexOfEllipsis + numberOfRemovedGlyphs, numberOfLaidOutGlyphs * sizeof(GlyphInfo));
562 memcpy(glyphPositions, glyphPositions + startIndexOfEllipsis + numberOfRemovedGlyphs, numberOfLaidOutGlyphs * sizeof(Vector2));
563 mImpl->mVisualModel->SetStartIndexOfElidedGlyphs(indexOfEllipsis);
565 else // DevelText::EllipsisPosition::END
567 numberOfLaidOutGlyphs = numberOfActualLaidOutGlyphs - numberOfRemovedGlyphs;
568 mImpl->mVisualModel->SetEndIndexOfElidedGlyphs(indexOfEllipsis);
575 return numberOfLaidOutGlyphs;
578 const Vector4* const View::GetColors() const
580 if(mImpl->mVisualModel)
582 return mImpl->mVisualModel->mColors.Begin();
588 const ColorIndex* const View::GetColorIndices() const
590 if(mImpl->mVisualModel)
592 return mImpl->mVisualModel->mColorIndices.Begin();
598 const Vector4* const View::GetBackgroundColors() const
600 if(mImpl->mVisualModel)
602 return mImpl->mVisualModel->mBackgroundColors.Begin();
608 const ColorIndex* const View::GetBackgroundColorIndices() const
610 if(mImpl->mVisualModel)
612 return mImpl->mVisualModel->mBackgroundColorIndices.Begin();
618 bool const View::IsMarkupBackgroundColorSet() const
620 if(mImpl->mVisualModel)
622 return (mImpl->mVisualModel->mBackgroundColors.Count() > 0);
628 const Vector4& View::GetTextColor() const
630 if(mImpl->mVisualModel)
632 return mImpl->mVisualModel->GetTextColor();
634 return Vector4::ZERO;
637 const Vector2& View::GetShadowOffset() const
639 if(mImpl->mVisualModel)
641 return mImpl->mVisualModel->GetShadowOffset();
643 return Vector2::ZERO;
646 const Vector4& View::GetShadowColor() const
648 if(mImpl->mVisualModel)
650 return mImpl->mVisualModel->GetShadowColor();
652 return Vector4::ZERO;
655 const Vector4& View::GetUnderlineColor() const
657 if(mImpl->mVisualModel)
659 return mImpl->mVisualModel->GetUnderlineColor();
661 return Vector4::ZERO;
664 bool View::IsUnderlineEnabled() const
666 if(mImpl->mVisualModel)
668 return mImpl->mVisualModel->IsUnderlineEnabled();
673 const GlyphInfo* View::GetHyphens() const
675 if(mImpl->mVisualModel)
677 return mImpl->mVisualModel->mHyphen.glyph.Begin();
683 const Length* View::GetHyphenIndices() const
685 if(mImpl->mVisualModel)
687 return mImpl->mVisualModel->mHyphen.index.Begin();
693 Length View::GetHyphensCount() const
695 if(mImpl->mVisualModel)
697 return mImpl->mVisualModel->mHyphen.glyph.Size();
702 float View::GetUnderlineHeight() const
704 if(mImpl->mVisualModel)
706 return mImpl->mVisualModel->GetUnderlineHeight();
711 Text::Underline::Type View::GetUnderlineType() const
713 Text::Underline::Type type = Text::Underline::Type::SOLID;
714 if(mImpl->mVisualModel)
716 type = mImpl->mVisualModel->GetUnderlineType();
721 float View::GetDashedUnderlineWidth() const
724 if(mImpl->mVisualModel)
726 width = mImpl->mVisualModel->GetDashedUnderlineWidth();
731 float View::GetDashedUnderlineGap() const
734 if(mImpl->mVisualModel)
736 gap = mImpl->mVisualModel->GetDashedUnderlineGap();
741 Length View::GetNumberOfUnderlineRuns() const
743 if(mImpl->mVisualModel)
745 return mImpl->mVisualModel->GetNumberOfUnderlineRuns();
751 void View::GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns,
752 UnderlineRunIndex index,
753 Length numberOfRuns) const
755 if(mImpl->mVisualModel)
757 mImpl->mVisualModel->GetUnderlineRuns(underlineRuns,
763 const Vector4& View::GetOutlineColor() const
765 if(mImpl->mVisualModel)
767 return mImpl->mVisualModel->GetOutlineColor();
769 return Vector4::ZERO;
772 uint16_t View::GetOutlineWidth() const
774 if(mImpl->mVisualModel)
776 return mImpl->mVisualModel->GetOutlineWidth();
781 DevelText::EllipsisPosition::Type View::GetEllipsisPosition() const
783 DevelText::EllipsisPosition::Type ellipsisPosition = DevelText::EllipsisPosition::END;
784 if(mImpl->mVisualModel)
786 const VisualModel& model = *mImpl->mVisualModel;
787 ellipsisPosition = model.GetEllipsisPosition();
790 return ellipsisPosition;
793 bool View::IsTextElideEnabled() const
795 bool isTextElideEnabled = false;
797 if(mImpl->mVisualModel)
799 const VisualModel& model = *mImpl->mVisualModel;
800 isTextElideEnabled = model.IsTextElideEnabled();
803 return isTextElideEnabled;
806 GlyphIndex View::GetStartIndexOfElidedGlyphs() const
808 GlyphIndex startIndexOfElidedGlyphs = 0u;
810 if(mImpl->mVisualModel)
812 const VisualModel& model = *mImpl->mVisualModel;
813 startIndexOfElidedGlyphs = model.GetStartIndexOfElidedGlyphs();
816 return startIndexOfElidedGlyphs;
819 GlyphIndex View::GetEndIndexOfElidedGlyphs() const
821 GlyphIndex endIndexOfElidedGlyphs = 0u;
823 if(mImpl->mVisualModel)
825 const VisualModel& model = *mImpl->mVisualModel;
826 endIndexOfElidedGlyphs = model.GetEndIndexOfElidedGlyphs();
829 return endIndexOfElidedGlyphs;
832 GlyphIndex View::GetFirstMiddleIndexOfElidedGlyphs() const
834 GlyphIndex firstMiddleIndexOfElidedGlyphs = 0u;
836 if(mImpl->mVisualModel)
838 const VisualModel& model = *mImpl->mVisualModel;
839 firstMiddleIndexOfElidedGlyphs = model.GetFirstMiddleIndexOfElidedGlyphs();
842 return firstMiddleIndexOfElidedGlyphs;
845 GlyphIndex View::GetSecondMiddleIndexOfElidedGlyphs() const
847 GlyphIndex secondMiddleIndexOfElidedGlyphs = 0u;
849 if(mImpl->mVisualModel)
851 const VisualModel& model = *mImpl->mVisualModel;
852 secondMiddleIndexOfElidedGlyphs = model.GetSecondMiddleIndexOfElidedGlyphs();
855 return secondMiddleIndexOfElidedGlyphs;
858 const Vector4& View::GetStrikethroughColor() const
860 return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetStrikethroughColor() : Vector4::ZERO;
863 bool View::IsStrikethroughEnabled() const
865 return (mImpl->mVisualModel) ? mImpl->mVisualModel->IsStrikethroughEnabled() : false;
868 float View::GetStrikethroughHeight() const
870 return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetStrikethroughHeight() : 0.0f;
873 Length View::GetNumberOfStrikethroughRuns() const
875 if(mImpl->mVisualModel)
877 return mImpl->mVisualModel->GetNumberOfStrikethroughRuns();
883 void View::GetStrikethroughRuns(StrikethroughGlyphRun* strikethroughRuns,
884 StrikethroughRunIndex index,
885 Length numberOfRuns) const
887 if(mImpl->mVisualModel)
889 mImpl->mVisualModel->GetStrikethroughRuns(strikethroughRuns,
895 Length View::GetNumberOfBoundedParagraphRuns() const
897 if(mImpl->mLogicalModel)
899 return mImpl->mLogicalModel->GetNumberOfBoundedParagraphRuns();
905 const Vector<BoundedParagraphRun>& View::GetBoundedParagraphRuns() const
907 return mImpl->mLogicalModel->GetBoundedParagraphRuns();
910 Length View::GetNumberOfCharacterSpacingGlyphRuns() const
912 return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetNumberOfCharacterSpacingGlyphRuns() : 0u;
915 const Vector<CharacterSpacingGlyphRun>& View::GetCharacterSpacingGlyphRuns() const
917 return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetCharacterSpacingGlyphRuns() : GetEmptyCharacterSpacingGlyphRuns();
920 const float View::GetCharacterSpacing() const
922 return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetCharacterSpacing() : 0.f;
925 const Character* View::GetTextBuffer() const
927 return (mImpl->mVisualModel) ? mImpl->mLogicalModel->mText.Begin() : nullptr;
930 const Vector<CharacterIndex>& View::GetGlyphsToCharacters() const
932 return mImpl->mVisualModel->GetGlyphsToCharacters();
937 } // namespace Toolkit