[LyX/master] Handle the case where breakAt cuts after trailing space
Jean-Marc Lasgouttes
lasgouttes at lyx.org
Tue Dec 7 15:47:01 UTC 2021
commit 6e6976fbc5a61928c51c5193de985e26d94454bd
Author: Jean-Marc Lasgouttes <lasgouttes at lyx.org>
Date: Tue Aug 31 15:58:56 2021 +0200
Handle the case where breakAt cuts after trailing space
In this case, the extra element returned should empty but valid. The
row flag BreakAfter is set to indicate that we have a break there
(this principle will be used more generally in a forthcoming commit).
To detect that we cut at the trailing space, it is necessary to rely
on the difference between QTextLine::horizontalAdvance() and
QTextLine::naturalTextWidth() when the flag
QTextOption::IncludeTrailingSpaces is used: the trailing space is
taken into account in the later, but not in the former.
Somme comments have been added to make code intent clearer.
---
src/Row.cpp | 18 ++++++++++++++----
src/TextMetrics.cpp | 3 ++-
src/frontends/qt/GuiFontMetrics.cpp | 10 ++++++++--
3 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/src/Row.cpp b/src/Row.cpp
index 6e975a5..38dbb85 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -142,13 +142,19 @@ Row::Element Row::Element::splitAt(int w, bool force)
dim.wid = w;
int const i = fm.breakAt(str, dim.wid, isRTL(), force);
if (i != -1) {
+ //Create a second row element to return
Element ret(STRING, pos + i, font, change);
ret.str = str.substr(i);
ret.endpos = ret.pos + ret.str.length();
+ // Copy the after flags of the original element to the second one.
ret.row_flags = row_flags & (CanBreakInside | AfterFlags);
+
+ // Now update ourselves
str.erase(i);
endpos = pos + i;
- //lyxerr << "breakAt(" << w << ") Row element Broken at " << x << "(w(str)=" << fm.width(str) << "): e=" << *this << endl;
+ // Row should be broken after the original element
+ row_flags = (row_flags & ~AfterFlags) | BreakAfter;
+ //LYXERR0("breakAt(" << w << ") Row element Broken at " << w << "(w(str)=" << fm.width(str) << "): e=" << *this);
return ret;
}
@@ -251,7 +257,7 @@ ostream & operator<<(ostream & os, Row::Element const & e)
os << "INVALID: ";
break;
}
- os << "width=" << e.full_width();
+ os << "width=" << e.full_width() << ", row_flags=" << e.row_flags;
return os;
}
@@ -522,7 +528,7 @@ Row::Elements Row::shortenIfNeeded(int const w, int const next_width)
* break-up.
*/
Element remainder = brk.splitAt(min(w - wid_brk, brk.dim.wid - 2), !word_wrap);
- if (remainder.isValid()) {
+ if (brk.row_flags & BreakAfter) {
/* if this element originally did not cause a row overflow
* in itself, and the remainder of the row would still be
* too large after breaking, then we will have issues in
@@ -544,7 +550,11 @@ Row::Elements Row::shortenIfNeeded(int const w, int const next_width)
*cit_brk = brk;
dim_.wid = wid_brk + brk.dim.wid;
// If there are other elements, they should be removed.
- return splitFrom(elements_, next(cit_brk, 1), remainder);
+ // remainder can be empty when splitting at trailing space
+ if (remainder.str.empty())
+ return splitFrom(elements_, next(cit_brk, 1));
+ else
+ return splitFrom(elements_, next(cit_brk, 1), remainder);
}
}
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index c7e84f6..37894f6 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -1157,7 +1157,8 @@ RowList TextMetrics::breakParagraph(Row const & bigrow) const
// Add a new next element on the pile
if (next_elt.isValid()) {
// do as if we inserted this element in the original row
- fcit.put(next_elt);
+ if (!next_elt.str.empty())
+ fcit.put(next_elt);
need_new_row = true;
}
}
diff --git a/src/frontends/qt/GuiFontMetrics.cpp b/src/frontends/qt/GuiFontMetrics.cpp
index 56ed676..47537ae 100644
--- a/src/frontends/qt/GuiFontMetrics.cpp
+++ b/src/frontends/qt/GuiFontMetrics.cpp
@@ -525,6 +525,9 @@ GuiFontMetrics::breakAt_helper(docstring const & s, int const x,
QTextOption to;
to.setWrapMode(force ? QTextOption::WrapAtWordBoundaryOrAnywhere
: QTextOption::WordWrap);
+ // Let QTextLine::naturalTextWidth() account for trailing spaces
+ // (horizontalAdvance() still does not).
+ to.setFlags(QTextOption::IncludeTrailingSpaces);
tl.setTextOption(to);
tl.beginLayout();
QTextLine line = tl.createLine();
@@ -557,8 +560,11 @@ GuiFontMetrics::breakAt_helper(docstring const & s, int const x,
--len;
LASSERT(len > 0 || qlen == 0, /**/);
#endif
- // Do not cut is the string is already short enough
- if (len == static_cast<int>(s.length())) {
+ // Do not cut is the string is already short enough. We rely on
+ // naturalTextWidth() to catch the case where we cut at the trailing
+ // space.
+ if (len == static_cast<int>(s.length())
+ && line.naturalTextWidth() <= x) {
len = -1;
#if QT_VERSION < 0x050000
// With some monospace fonts, the value of horizontalAdvance()
More information about the lyx-cvs
mailing list