commit 7950ace3d96543e3099aa3bde823f970a1ce6a86
Author: Jean-Marc Lasgouttes <[email protected]>
Date: Sat Nov 3 15:55:33 2018 +0000
Fix selection of unmarked RtL text
With Qt 5.11 at least, RtL text will be drawn RtL even when the
(undocumented) flag Qt::TextForceLeftToRight is applied to the
QTextLayout object. This creates selection issues for Hebrew text
marked as English.
The solution is to do the same as in breakAt_helper, that is prepend
the string with a direction override unicode character.
Doing this requires to introduce a TEXTLAYOUT_OFFSET constant that has
to be used wisely to account for this extra character.
Fixes bug #11284.
(cherry picked from commit 1bed76e2a1057ab2f3f33f01ec23956653265d4a)
---
src/frontends/qt4/GuiFontMetrics.cpp | 27 ++++++++++++++++++++++++---
status.23x | 2 ++
2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/src/frontends/qt4/GuiFontMetrics.cpp
b/src/frontends/qt4/GuiFontMetrics.cpp
index b9eab85..8ed8228 100644
--- a/src/frontends/qt4/GuiFontMetrics.cpp
+++ b/src/frontends/qt4/GuiFontMetrics.cpp
@@ -237,12 +237,27 @@ GuiFontMetrics::getTextLayout(docstring const & s, bool
const rtl,
PROFILE_CACHE_MISS(getTextLayout);
auto const ptl = make_shared<QTextLayout>();
ptl->setCacheEnabled(true);
- ptl->setText(toqstr(s));
QFont copy = font_;
copy.setWordSpacing(wordspacing);
ptl->setFont(copy);
+#if 1
+ /* Use unicode override characters to enforce drawing direction
+ * Source: http://www.iamcal.com/understanding-bidirectional-text/
+ */
+ if (rtl)
+ // Right-to-left override: forces to draw text right-to-left
+ ptl->setText(QChar(0x202E) + toqstr(s));
+ else
+ // Left-to-right override: forces to draw text left-to-right
+ ptl->setText(QChar(0x202D) + toqstr(s));
+#define TEXTLAYOUT_OFFSET 1
+#else
+ // FIXME: This does not work with Qt 5.11 (ticket #11284).
// Note that both setFlags and the enums are undocumented
ptl->setFlags(rtl ? Qt::TextForceRightToLeft :
Qt::TextForceLeftToRight);
+ ptl->setText(toqstr(s));
+#define TEXTLAYOUT_OFFSET 0
+#endif
ptl->beginLayout();
ptl->createLine();
ptl->endLayout();
@@ -261,7 +276,9 @@ int GuiFontMetrics::pos2x(docstring const & s, int pos,
bool const rtl,
* not be the same when there are high-plan unicode characters
* (bug #10443).
*/
- int const qpos = toqstr(s.substr(0, pos)).length();
+ // TEXTLAYOUT_OFFSET accounts for a possible direction override
+ // character in front of the string.
+ int const qpos = toqstr(s.substr(0, pos)).length() + TEXTLAYOUT_OFFSET;
return static_cast<int>(tl->lineForTextPosition(qpos).cursorToX(qpos));
}
@@ -303,7 +320,9 @@ int GuiFontMetrics::x2pos(docstring const & s, int & x,
bool const rtl,
* (bug #10443).
*/
#if QT_VERSION < 0x040801 || QT_VERSION >= 0x050100
- return qstring_to_ucs4(tl->text().left(qpos)).length();
+ int pos = qstring_to_ucs4(tl->text().left(qpos)).length();
+ // there may be a direction override character in front of the string.
+ return max(pos - TEXTLAYOUT_OFFSET, 0);
#else
/* Due to QTBUG-25536 in 4.8.1 <= Qt < 5.1.0, the string returned
* by QString::toUcs4 (used by qstring_to_ucs4) may have wrong
@@ -313,6 +332,8 @@ int GuiFontMetrics::x2pos(docstring const & s, int & x,
bool const rtl,
* worthwhile to implement a dichotomy search if this shows up
* under a profiler.
*/
+ // there may be a direction override character in front of the string.
+ qpos = max(qpos - TEXTLAYOUT_OFFSET, 0);
int pos = min(qpos, static_cast<int>(s.length()));
while (pos >= 0 && toqstr(s.substr(0, pos)).length() != qpos)
--pos;
diff --git a/status.23x b/status.23x
index 44e2b2e..a1fb4d9 100644
--- a/status.23x
+++ b/status.23x
@@ -56,6 +56,8 @@ What's new
- Fix reloading of local layout file (bug 11120).
+- Fix selection of unmarked RtL characters with Qt 5.11 (bug 11284).
+
* INTERNALS