9struct LineBreakerWithLittleRounding {
10 LineBreakerWithLittleRounding(
SkScalar maxWidth,
bool applyRoundingHack)
23 auto val = std::fabs(
width);
28 }
else if (val < 100000) {
36 }
else if (val < 100000) {
52void TextWrapper::lookAhead(
SkScalar maxWidth, Cluster* endOfClusters,
bool applyRoundingHack) {
55 fEndLine.metrics().clean();
56 fWords.startFrom(fEndLine.startCluster(), fEndLine.startPos());
57 fClusters.startFrom(fEndLine.startCluster(), fEndLine.startPos());
58 fClip.startFrom(fEndLine.startCluster(), fEndLine.startPos());
60 LineBreakerWithLittleRounding breaker(maxWidth, applyRoundingHack);
61 Cluster* nextNonBreakingSpace =
nullptr;
62 for (
auto cluster = fEndLine.endCluster(); cluster < endOfClusters; ++cluster) {
63 if (cluster->isHardBreak()) {
66 SkScalar width = fWords.width() + fClusters.width() + cluster->width();
67 breaker.breakLine(
width)) {
68 if (cluster->isWhitespaceBreak()) {
70 fClusters.extend(cluster);
71 fMinIntrinsicWidth =
std::max(fMinIntrinsicWidth, this->getClustersTrimmedWidth());
72 fWords.extend(fClusters);
74 }
else if (cluster->run().isPlaceholder()) {
75 if (!fClusters.empty()) {
77 fMinIntrinsicWidth =
std::max(fMinIntrinsicWidth, this->getClustersTrimmedWidth());
78 fWords.extend(fClusters);
81 if (cluster->width() > maxWidth && fWords.empty()) {
84 fClusters.extend(cluster);
85 fTooLongCluster =
true;
94 SkScalar nextWordLength = fClusters.width();
95 SkScalar nextShortWordLength = nextWordLength;
96 for (
auto further = cluster; further != endOfClusters; ++further) {
97 if (further->isSoftBreak() || further->isHardBreak() || further->isWhitespaceBreak()) {
100 if (further->run().isPlaceholder()) {
105 if (nextWordLength > 0 && nextWordLength <= maxWidth && further->isIntraWordBreak()) {
107 nextNonBreakingSpace = further;
108 nextShortWordLength = nextWordLength;
113 nextWordLength =
std::max(nextWordLength, further->width());
115 nextWordLength += further->width();
118 if (nextWordLength > maxWidth) {
119 if (nextNonBreakingSpace !=
nullptr) {
122 if (
SkScalar shortLength = fWords.width() + nextShortWordLength;
123 !breaker.breakLine(shortLength)) {
125 fClusters = TextStretch(fClusters.startCluster(), nextNonBreakingSpace, fClusters.metrics().getForceStrut());
126 fMinIntrinsicWidth =
std::max(fMinIntrinsicWidth, nextShortWordLength);
127 fWords.extend(fClusters);
136 fMinIntrinsicWidth =
std::max(fMinIntrinsicWidth, nextWordLength);
137 if (fClusters.endPos() - fClusters.startPos() > 1 ||
146 if (cluster->width() > maxWidth) {
147 fClusters.extend(cluster);
148 fTooLongCluster =
true;
154 if (cluster->run().isPlaceholder()) {
155 if (!fClusters.empty()) {
157 fMinIntrinsicWidth =
std::max(fMinIntrinsicWidth, getClustersTrimmedWidth());
158 fWords.extend(fClusters);
162 fMinIntrinsicWidth =
std::max(fMinIntrinsicWidth, cluster->width());
163 fWords.extend(cluster);
165 fClusters.extend(cluster);
168 if (fClusters.endOfWord()) {
169 fMinIntrinsicWidth =
std::max(fMinIntrinsicWidth, getClustersTrimmedWidth());
170 fWords.extend(fClusters);
174 if ((fHardLineBreak = cluster->isHardBreak())) {
181void TextWrapper::moveForward(
bool hasEllipsis) {
187 if (!fWords.empty()) {
188 fEndLine.extend(fWords);
189#ifdef SK_IGNORE_SKPARAGRAPH_ELLIPSIS_FIX
190 if (!fTooLongWord || hasEllipsis) {
192 if (!fTooLongWord && !hasEllipsis) {
197 if (!fClusters.empty()) {
198 fEndLine.extend(fClusters);
199 if (!fTooLongCluster) {
204 if (!fClip.empty()) {
206 fEndLine.metrics().add(fClip.metrics());
211void TextWrapper::trimEndSpaces(
TextAlign align) {
213 fEndLine.saveBreak();
215 for (
auto cluster = fEndLine.endCluster();
216 cluster >= fEndLine.startCluster() && cluster->isWhitespaceBreak();
218 fEndLine.trim(cluster);
223SkScalar TextWrapper::getClustersTrimmedWidth() {
226 bool trailingSpaces =
true;
227 for (
auto cluster = fClusters.endCluster(); cluster >= fClusters.startCluster(); --cluster) {
228 if (cluster->run().isPlaceholder()) {
231 if (trailingSpaces) {
232 if (!cluster->isWhitespaceBreak()) {
233 width += cluster->trimmedWidth(cluster->endPos());
234 trailingSpaces =
false;
238 width += cluster->width();
244std::tuple<Cluster*, size_t, SkScalar> TextWrapper::trimStartSpaces(Cluster* endOfClusters) {
246 if (fHardLineBreak) {
248 auto width = fEndLine.width();
249 auto cluster = fEndLine.endCluster() + 1;
250 while (cluster < fEndLine.breakCluster() && cluster->isWhitespaceBreak()) {
251 width += cluster->width();
254 return std::make_tuple(fEndLine.breakCluster() + 1, 0,
width);
259 auto width = fEndLine.widthWithGhostSpaces();
260 auto cluster = fEndLine.breakCluster() + 1;
261 while (cluster < endOfClusters && cluster->isWhitespaceBreak()) {
262 width += cluster->width();
266 if (fEndLine.breakCluster()->isWhitespaceBreak() && fEndLine.breakCluster() < endOfClusters) {
270 fEndLine.shiftBreak();
273 return std::make_tuple(cluster, 0,
width);
296 bool firstLine =
true;
298 SkScalar softLineMaxIntrinsicWidth = 0;
299 fEndLine = TextStretch(span.begin(), span.begin(), parent->
strutForceHeight());
300 auto end = span.end() - 1;
301 auto start = span.begin();
303 bool needEllipsis =
false;
304 while (fEndLine.endCluster() !=
end) {
308 auto lastLine = (hasEllipsis && unlimitedLines) || fLineNumber >= maxLines;
309 needEllipsis = hasEllipsis && !endlessLine && lastLine;
311 this->moveForward(needEllipsis);
312 needEllipsis &= fEndLine.endCluster() <
end - 1;
315 this->trimEndSpaces(align);
321 std::tie(startLine,
pos, widthWithSpaces) = this->trimStartSpaces(
end);
323 if (needEllipsis && !fHardLineBreak) {
325 fEndLine.restoreBreak();
326 widthWithSpaces = fEndLine.widthWithGhostSpaces();
330 if (fEndLine.metrics().isClean()) {
335 Run* lastRun =
nullptr;
336 for (
auto cluster = fEndLine.startCluster(); cluster <= fEndLine.endCluster(); ++cluster) {
337 auto r = cluster->runOrNull();
352 maxRunMetrics = fEndLine.metrics();
353 maxRunMetrics.fForceStrut =
false;
356 TextRange textExcludingSpaces(fEndLine.startCluster()->textRange().start, fEndLine.endCluster()->textRange().end);
357 TextRange text(fEndLine.startCluster()->textRange().start, fEndLine.breakCluster()->textRange().start);
359 if (startLine ==
end) {
366 if (disableFirstAscent && firstLine) {
367 fEndLine.metrics().fAscent = fEndLine.metrics().fRawAscent;
369 if (disableLastDescent && (lastLine || (startLine ==
end && !fHardLineBreak ))) {
370 fEndLine.metrics().fDescent = fEndLine.metrics().fRawDescent;
378 SkScalar lineHeight = fEndLine.metrics().height();
381 if (fEndLine.empty()) {
383 textExcludingSpaces.
end = textExcludingSpaces.
start;
390 addLine(textExcludingSpaces,
392 textIncludingNewlines, clusters, clustersWithGhosts, widthWithSpaces,
398 needEllipsis && !fHardLineBreak);
400 softLineMaxIntrinsicWidth += widthWithSpaces;
402 fMaxIntrinsicWidth =
std::max(fMaxIntrinsicWidth, softLineMaxIntrinsicWidth);
403 if (fHardLineBreak) {
404 softLineMaxIntrinsicWidth = 0;
407 fHeight += lineHeight;
408 if (!fHardLineBreak || startLine !=
end) {
411 fEndLine.startFrom(startLine,
pos);
412 parent->fMaxWidthWithTrailingSpaces =
std::max(parent->fMaxWidthWithTrailingSpaces, widthWithSpaces);
414 if (hasEllipsis && unlimitedLines) {
417 if (!fHardLineBreak) {
420 }
else if (lastLine) {
422 fHardLineBreak =
false;
431 if (fEndLine.endCluster() !=
nullptr) {
432 auto lastWordLength = 0.0f;
433 auto cluster = fEndLine.endCluster();
434 while (cluster !=
end || cluster->endPos() <
end->endPos()) {
435 fExceededMaxLines =
true;
436 if (cluster->isHardBreak()) {
438 fMaxIntrinsicWidth =
std::max(fMaxIntrinsicWidth, softLineMaxIntrinsicWidth);
439 softLineMaxIntrinsicWidth = 0;
440 fMinIntrinsicWidth =
std::max(fMinIntrinsicWidth, lastWordLength);
442 }
else if (cluster->isWhitespaceBreak()) {
444 softLineMaxIntrinsicWidth += cluster->width();
445 fMinIntrinsicWidth =
std::max(fMinIntrinsicWidth, lastWordLength);
447 }
else if (cluster->run().isPlaceholder()) {
449 fMinIntrinsicWidth =
std::max(fMinIntrinsicWidth, lastWordLength);
451 softLineMaxIntrinsicWidth += cluster->width();
452 fMinIntrinsicWidth =
std::max(fMinIntrinsicWidth, cluster->width());
456 softLineMaxIntrinsicWidth += cluster->width();
457 lastWordLength += cluster->width();
461 fMinIntrinsicWidth =
std::max(fMinIntrinsicWidth, lastWordLength);
462 fMaxIntrinsicWidth =
std::max(fMaxIntrinsicWidth, softLineMaxIntrinsicWidth);
464 if (parent->
lines().empty()) {
466 if (disableFirstAscent) {
467 fEndLine.metrics().fAscent = fEndLine.metrics().fRawAscent;
469 if (disableLastDescent && !fHardLineBreak) {
470 fEndLine.metrics().fDescent = fEndLine.metrics().fRawDescent;
472 fHeight =
std::max(fHeight, fEndLine.metrics().height());
476 if (fHardLineBreak) {
477 if (disableLastDescent) {
478 fEndLine.metrics().fDescent = fEndLine.metrics().fRawDescent;
488 addLine(fEndLine.breakCluster()->textRange(),
489 fEndLine.breakCluster()->textRange(),
490 fEndLine.endCluster()->textRange(),
500 fHeight += fEndLine.metrics().height();
501 parent->
lines().back().setMaxRunMetrics(maxRunMetrics);
504 if (parent->
lines().empty()) {
508 if (disableFirstAscent) {
511 if (disableLastDescent) {
static bool SkIsFinite(T x, Pack... values)
#define SkScalarFloorToScalar(x)
#define SkScalarRoundToScalar(x)
const bool fApplyRoundingHack
constexpr size_t size() const
TextRange textRange() const
void updateLineMetrics(InternalLineMetrics &metrics)
SkSpan< TextLine > lines()
InternalLineMetrics getEmptyMetrics() const
InternalLineMetrics strutMetrics() const
SkSpan< Cluster > clusters()
SkSpan< const char > text() const
bool strutForceHeight() const
bool getApplyRoundingHack() const
const ParagraphStyle & paragraphStyle() const
bool strutEnabled() const
void updateMetrics(InternalLineMetrics *endlineMetrics)
PlaceholderStyle * placeholderStyle() const
std::function< void(TextRange textExcludingSpaces, TextRange text, TextRange textIncludingNewlines, ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar AddLineToParagraph, size_t startClip, size_t endClip, SkVector offset, SkVector advance, InternalLineMetrics metrics, bool addEllipsis)> AddLineToParagraph
void breakTextIntoLines(ParagraphImpl *parent, SkScalar maxWidth, const AddLineToParagraph &addLine)
static float max(float r, float g, float b)
static float min(float r, float g, float b)
static constexpr SkPoint Make(float x, float y)
TextHeightBehavior getTextHeightBehavior() const
TextAlign effective_align() const
size_t getMaxLines() const