2 * Copyright (c) 2023 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 // Make sure that out-of-boundary does not occur.
553 if(secondMiddleIndexOfElidedGlyphs + numberOfSecondHalfGlyphs > numberOfGlyphs)
555 numberOfSecondHalfGlyphs = numberOfGlyphs - secondMiddleIndexOfElidedGlyphs;
558 //Copy elided glyphs after the ellipsis glyph.
559 memcpy(glyphs + firstMiddleIndexOfElidedGlyphs + 1u, glyphs + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(GlyphInfo));
560 memcpy(glyphPositions + firstMiddleIndexOfElidedGlyphs + 1u, glyphPositions + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(Vector2));
563 else if(ellipsisPosition == DevelText::EllipsisPosition::START)
565 numberOfLaidOutGlyphs = numberOfActualLaidOutGlyphs - numberOfRemovedGlyphs;
566 //Copy elided glyphs after the ellipsis glyph.
567 memcpy(glyphs, glyphs + startIndexOfEllipsis + numberOfRemovedGlyphs, numberOfLaidOutGlyphs * sizeof(GlyphInfo));
568 memcpy(glyphPositions, glyphPositions + startIndexOfEllipsis + numberOfRemovedGlyphs, numberOfLaidOutGlyphs * sizeof(Vector2));
569 mImpl->mVisualModel->SetStartIndexOfElidedGlyphs(indexOfEllipsis);
571 else // DevelText::EllipsisPosition::END
573 numberOfLaidOutGlyphs = numberOfActualLaidOutGlyphs - numberOfRemovedGlyphs;
574 mImpl->mVisualModel->SetEndIndexOfElidedGlyphs(indexOfEllipsis);
581 return numberOfLaidOutGlyphs;
584 const Vector4* View::GetColors() const
586 if(mImpl->mVisualModel)
588 return mImpl->mVisualModel->mColors.Begin();
594 const ColorIndex* View::GetColorIndices() const
596 if(mImpl->mVisualModel)
598 return mImpl->mVisualModel->mColorIndices.Begin();
604 const Vector4* View::GetBackgroundColors() const
606 if(mImpl->mVisualModel)
608 return mImpl->mVisualModel->mBackgroundColors.Begin();
614 const ColorIndex* View::GetBackgroundColorIndices() const
616 if(mImpl->mVisualModel)
618 return mImpl->mVisualModel->mBackgroundColorIndices.Begin();
624 bool View::IsMarkupBackgroundColorSet() const
626 if(mImpl->mVisualModel)
628 return (mImpl->mVisualModel->mBackgroundColors.Count() > 0);
634 const Vector4& View::GetTextColor() const
636 if(mImpl->mVisualModel)
638 return mImpl->mVisualModel->GetTextColor();
640 return Vector4::ZERO;
643 const Vector2& View::GetShadowOffset() const
645 if(mImpl->mVisualModel)
647 return mImpl->mVisualModel->GetShadowOffset();
649 return Vector2::ZERO;
652 const Vector4& View::GetShadowColor() const
654 if(mImpl->mVisualModel)
656 return mImpl->mVisualModel->GetShadowColor();
658 return Vector4::ZERO;
661 const Vector4& View::GetUnderlineColor() const
663 if(mImpl->mVisualModel)
665 return mImpl->mVisualModel->GetUnderlineColor();
667 return Vector4::ZERO;
670 bool View::IsUnderlineEnabled() const
672 if(mImpl->mVisualModel)
674 return mImpl->mVisualModel->IsUnderlineEnabled();
679 bool View::IsMarkupUnderlineSet() const
681 return (GetNumberOfUnderlineRuns() > 0u);
684 const GlyphInfo* View::GetHyphens() const
686 if(mImpl->mVisualModel)
688 return mImpl->mVisualModel->mHyphen.glyph.Begin();
694 const Length* View::GetHyphenIndices() const
696 if(mImpl->mVisualModel)
698 return mImpl->mVisualModel->mHyphen.index.Begin();
704 Length View::GetHyphensCount() const
706 if(mImpl->mVisualModel)
708 return mImpl->mVisualModel->mHyphen.glyph.Size();
713 float View::GetUnderlineHeight() const
715 if(mImpl->mVisualModel)
717 return mImpl->mVisualModel->GetUnderlineHeight();
722 Text::Underline::Type View::GetUnderlineType() const
724 Text::Underline::Type type = Text::Underline::Type::SOLID;
725 if(mImpl->mVisualModel)
727 type = mImpl->mVisualModel->GetUnderlineType();
732 float View::GetDashedUnderlineWidth() const
735 if(mImpl->mVisualModel)
737 width = mImpl->mVisualModel->GetDashedUnderlineWidth();
742 float View::GetDashedUnderlineGap() const
745 if(mImpl->mVisualModel)
747 gap = mImpl->mVisualModel->GetDashedUnderlineGap();
752 Length View::GetNumberOfUnderlineRuns() const
754 if(mImpl->mVisualModel)
756 return mImpl->mVisualModel->GetNumberOfUnderlineRuns();
762 void View::GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns,
763 UnderlineRunIndex index,
764 Length numberOfRuns) const
766 if(mImpl->mVisualModel)
768 mImpl->mVisualModel->GetUnderlineRuns(underlineRuns,
774 const Vector4& View::GetOutlineColor() const
776 if(mImpl->mVisualModel)
778 return mImpl->mVisualModel->GetOutlineColor();
780 return Vector4::ZERO;
783 uint16_t View::GetOutlineWidth() const
785 if(mImpl->mVisualModel)
787 return mImpl->mVisualModel->GetOutlineWidth();
792 DevelText::EllipsisPosition::Type View::GetEllipsisPosition() const
794 DevelText::EllipsisPosition::Type ellipsisPosition = DevelText::EllipsisPosition::END;
795 if(mImpl->mVisualModel)
797 const VisualModel& model = *mImpl->mVisualModel;
798 ellipsisPosition = model.GetEllipsisPosition();
801 return ellipsisPosition;
804 bool View::IsTextElideEnabled() const
806 bool isTextElideEnabled = false;
808 if(mImpl->mVisualModel)
810 const VisualModel& model = *mImpl->mVisualModel;
811 isTextElideEnabled = model.IsTextElideEnabled();
814 return isTextElideEnabled;
817 GlyphIndex View::GetStartIndexOfElidedGlyphs() const
819 GlyphIndex startIndexOfElidedGlyphs = 0u;
821 if(mImpl->mVisualModel)
823 const VisualModel& model = *mImpl->mVisualModel;
824 startIndexOfElidedGlyphs = model.GetStartIndexOfElidedGlyphs();
827 return startIndexOfElidedGlyphs;
830 GlyphIndex View::GetEndIndexOfElidedGlyphs() const
832 GlyphIndex endIndexOfElidedGlyphs = 0u;
834 if(mImpl->mVisualModel)
836 const VisualModel& model = *mImpl->mVisualModel;
837 endIndexOfElidedGlyphs = model.GetEndIndexOfElidedGlyphs();
840 return endIndexOfElidedGlyphs;
843 GlyphIndex View::GetFirstMiddleIndexOfElidedGlyphs() const
845 GlyphIndex firstMiddleIndexOfElidedGlyphs = 0u;
847 if(mImpl->mVisualModel)
849 const VisualModel& model = *mImpl->mVisualModel;
850 firstMiddleIndexOfElidedGlyphs = model.GetFirstMiddleIndexOfElidedGlyphs();
853 return firstMiddleIndexOfElidedGlyphs;
856 GlyphIndex View::GetSecondMiddleIndexOfElidedGlyphs() const
858 GlyphIndex secondMiddleIndexOfElidedGlyphs = 0u;
860 if(mImpl->mVisualModel)
862 const VisualModel& model = *mImpl->mVisualModel;
863 secondMiddleIndexOfElidedGlyphs = model.GetSecondMiddleIndexOfElidedGlyphs();
866 return secondMiddleIndexOfElidedGlyphs;
869 const Vector4& View::GetStrikethroughColor() const
871 return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetStrikethroughColor() : Vector4::ZERO;
874 bool View::IsStrikethroughEnabled() const
876 return (mImpl->mVisualModel) ? mImpl->mVisualModel->IsStrikethroughEnabled() : false;
879 bool View::IsMarkupStrikethroughSet() const
881 return (GetNumberOfStrikethroughRuns() > 0u);
884 float View::GetStrikethroughHeight() const
886 return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetStrikethroughHeight() : 0.0f;
889 Length View::GetNumberOfStrikethroughRuns() const
891 if(mImpl->mVisualModel)
893 return mImpl->mVisualModel->GetNumberOfStrikethroughRuns();
899 void View::GetStrikethroughRuns(StrikethroughGlyphRun* strikethroughRuns,
900 StrikethroughRunIndex index,
901 Length numberOfRuns) const
903 if(mImpl->mVisualModel)
905 mImpl->mVisualModel->GetStrikethroughRuns(strikethroughRuns,
911 Length View::GetNumberOfBoundedParagraphRuns() const
913 if(mImpl->mLogicalModel)
915 return mImpl->mLogicalModel->GetNumberOfBoundedParagraphRuns();
921 const Vector<BoundedParagraphRun>& View::GetBoundedParagraphRuns() const
923 return mImpl->mLogicalModel->GetBoundedParagraphRuns();
926 float View::GetCharacterSpacing() const
928 return mImpl->mVisualModel->GetCharacterSpacing();
931 const Character* View::GetTextBuffer() const
933 return mImpl->mLogicalModel->mText.Begin();
936 const Vector<CharacterIndex>& View::GetGlyphsToCharacters() const
938 return mImpl->mVisualModel->GetGlyphsToCharacters();
943 } // namespace Toolkit