Ellipsis attached to cluster, not word
Change-Id: I3bcef7e57a8f95a12743325363463a3a4039776e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/263206
Commit-Queue: Julia Lavrova <jlavrova@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/modules/skparagraph/src/TextWrapper.cpp b/modules/skparagraph/src/TextWrapper.cpp
index 813152b..972a21a 100644
--- a/modules/skparagraph/src/TextWrapper.cpp
+++ b/modules/skparagraph/src/TextWrapper.cpp
@@ -72,23 +72,29 @@
}
}
-void TextWrapper::moveForward() {
- do {
- if (!fWords.empty()) {
- fEndLine.extend(fWords);
- } else if (!fClusters.empty()) {
- fEndLine.extend(fClusters);
- fTooLongWord = false;
- fTooLongCluster = false;
- } else if (!fClip.empty() || (fTooLongWord && fTooLongCluster)) {
- // Flutter: forget the clipped cluster but keep the metrics
- fEndLine.metrics().add(fClip.metrics());
- fTooLongWord = false;
- fTooLongCluster = false;
- } else {
- break;
+void TextWrapper::moveForward(bool hasEllipsis) {
+
+ // We normally break lines by words.
+ // The only way we may go to clusters is if the word is too long or
+ // it's the first word and it has an ellipsis attached to it.
+ // If nothing fits we show the clipping.
+ if (!fWords.empty()) {
+ fEndLine.extend(fWords);
+ if (!fTooLongWord || hasEllipsis) {
+ return;
}
- } while (fTooLongWord || fTooLongCluster);
+ }
+ if (!fClusters.empty()) {
+ fEndLine.extend(fClusters);
+ if (!fTooLongCluster) {
+ return;
+ }
+ }
+
+ if (!fClip.empty()) {
+ // Flutter: forget the clipped cluster but keep the metrics
+ fEndLine.metrics().add(fClip.metrics());
+ }
}
// Special case for start/end cluster since they can be clipped
@@ -160,6 +166,7 @@
return std::make_tuple(cluster, 0, width);
}
+// TODO: refactor the code for line ending (with/without ellipsis)
void TextWrapper::breakTextIntoLines(ParagraphImpl* parent,
SkScalar maxWidth,
const AddLineToParagraph& addLine) {
@@ -169,7 +176,7 @@
auto span = parent->clusters();
if (span.size() == 0) {
- return;
+ return;
}
auto maxLines = parent->paragraphStyle().getMaxLines();
auto& ellipsisStr = parent->paragraphStyle().getEllipsis();
@@ -185,10 +192,10 @@
while (fEndLine.endCluster() != end) {
reset();
-
+ auto exceededLines = !endlessLine && fLineNumber >= maxLines;
fEndLine.metrics().clean();
lookAhead(maxWidth, end);
- moveForward();
+ moveForward(exceededLines && !ellipsisStr.isEmpty());
// Do not trim end spaces on the naturally last line of the left aligned text
trimEndSpaces(align);
@@ -204,9 +211,11 @@
SkScalarIsFinite(maxWidth) &&
!ellipsisStr.isEmpty();
- auto exceededLines = !endlessLine && fLineNumber >= maxLines;
-
- // TODO: perform ellipsis work here
+ if (needEllipsis && exceededLines && !fHardLineBreak) {
+ // This is what we need to do to preserve a space before the ellipsis
+ fEndLine.restoreBreak();
+ widthWithSpaces = fEndLine.withWithGhostSpaces();
+ }
// If the line is empty with the hard line break, let's take the paragraph font (flutter???)
if (fHardLineBreak && fEndLine.width() == 0) {
@@ -264,9 +273,11 @@
fEndLine.startFrom(startLine, pos);
parent->fMaxWidthWithTrailingSpaces = SkMaxScalar(parent->fMaxWidthWithTrailingSpaces, widthWithSpaces);
- if (exceededLines || (needEllipsis && endlessLine && !fHardLineBreak)) {
+ if (exceededLines) {
fHardLineBreak = false;
break;
+ } else if (endlessLine && needEllipsis) {
+ break;
}
++fLineNumber;
@@ -302,7 +313,6 @@
}
if (fHardLineBreak) {
-
// Last character is a line break
if (parent->strutEnabled()) {
// Make sure font metrics are not less than the strut