commit 4d6041a7b68de5856b657cfd3b735596b3d7e0e0
Author: Jean-Marc Lasgouttes <[email protected]>
Date: Mon Jan 27 18:38:21 2020 +0100
Adopt a 'belt and braces' approach to bidi forcing
There are two techniques that I know of for forcing the direction of a
string, regardlessly of whether its contents is naturally LtR, RtL or
undecided.
1/ The unicode LTR/LTR override characters. This is supposed to be the
clean way, however, it does not seem to work with Qt 5.14 (see
#11691).
2/ The undocumented QTextLayout::setFlags method. This is used
internally and allows to pass the (undocumented) flags
Qt::TextForceRightToLeft and Qt::TextForceLeftToRight. This was
used until we had issues with Qt 5.11 (see #11284).
In order to get the best of both worlds, this patch allows to enable
those two methods separately, and actually enables both at the same
time by default!
(hopefully) Fixes bug #11691.
---
src/frontends/qt/GuiFontMetrics.cpp | 59 +++++++++++++++++++++++++----------
1 files changed, 42 insertions(+), 17 deletions(-)
diff --git a/src/frontends/qt/GuiFontMetrics.cpp
b/src/frontends/qt/GuiFontMetrics.cpp
index 10ca292..acc8044 100644
--- a/src/frontends/qt/GuiFontMetrics.cpp
+++ b/src/frontends/qt/GuiFontMetrics.cpp
@@ -29,6 +29,25 @@
using namespace std;
using namespace lyx::support;
+/* Define what mechanism is used to enforce text direction. Different
+ * methods work with different Qt versions. Here we try to use both
+ * methods together.
+ */
+// Define to use unicode override characters to force direction
+#define BIDI_USE_OVERRIDE
+// Define to use flag to force direction
+#define BIDI_USE_FLAG
+
+#ifdef BIDI_USE_OVERRIDE
+# define BIDI_OFFSET 1
+#else
+# define BIDI_OFFSET 0
+#endif
+
+#if !defined(BIDI_USE_OVERRIDE) && !defined(BIDI_USE_FLAG)
+# error "Define at least one of BIDI_USE_OVERRIDE or BIDI_USE_FLAG"
+#endif
+
namespace std {
/*
@@ -268,7 +287,15 @@ GuiFontMetrics::getTextLayout(docstring const & s, bool
const rtl,
QFont copy = font_;
copy.setWordSpacing(wordspacing);
ptl->setFont(copy);
-#if 1
+
+#ifdef BIDI_USE_FLAG
+ /* Use undocumented flag to enforce drawing direction
+ * FIXME: This does not work with Qt 5.11 (ticket #11284).
+ */
+ ptl->setFlags(rtl ? Qt::TextForceRightToLeft :
Qt::TextForceLeftToRight);
+#endif
+
+#ifdef BIDI_USE_OVERRIDE
/* Use unicode override characters to enforce drawing direction
* Source: http://www.iamcal.com/understanding-bidirectional-text/
*/
@@ -278,14 +305,10 @@ GuiFontMetrics::getTextLayout(docstring const & s, bool
const rtl,
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();
@@ -304,9 +327,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).
*/
- // TEXTLAYOUT_OFFSET accounts for a possible direction override
+ // BIDI_OFFSET accounts for a possible direction override
// character in front of the string.
- int const qpos = toqstr(s.substr(0, pos)).length() + TEXTLAYOUT_OFFSET;
+ int const qpos = toqstr(s.substr(0, pos)).length() + BIDI_OFFSET;
return static_cast<int>(tl->lineForTextPosition(qpos).cursorToX(qpos));
}
@@ -350,7 +373,7 @@ int GuiFontMetrics::x2pos(docstring const & s, int & x,
bool const rtl,
#if QT_VERSION < 0x040801 || QT_VERSION >= 0x050100
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);
+ return max(pos - BIDI_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
@@ -361,7 +384,7 @@ int GuiFontMetrics::x2pos(docstring const & s, int & x,
bool const rtl,
* under a profiler.
*/
// there may be a direction override character in front of the string.
- qpos = max(qpos - TEXTLAYOUT_OFFSET, 0);
+ qpos = max(qpos - BIDI_OFFSET, 0);
int pos = min(qpos, static_cast<int>(s.length()));
while (pos >= 0 && toqstr(s.substr(0, pos)).length() != qpos)
--pos;
@@ -407,7 +430,14 @@ GuiFontMetrics::breakAt_helper(docstring const & s, int
const x,
// Unicode character ZERO WIDTH NO-BREAK SPACE
QChar const zerow_nbsp(0xfeff);
QString qs = zerow_nbsp + toqstr(s) + zerow_nbsp;
-#if 1
+#ifdef BIDI_USE_FLAG
+ /* Use undocumented flag to enforce drawing direction
+ * FIXME: This does not work with Qt 5.11 (ticket #11284).
+ */
+ tl.setFlags(rtl ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight);
+#endif
+
+#ifdef BIDI_USE_OVERRIDE
/* Use unicode override characters to enforce drawing direction
* Source: http://www.iamcal.com/understanding-bidirectional-text/
*/
@@ -417,13 +447,8 @@ GuiFontMetrics::breakAt_helper(docstring const & s, int
const x,
else
// Left-to-right override: forces to draw text left-to-right
qs = QChar(0x202D) + qs;
- int const offset = 2;
-#else
- // Alternative version that breaks with Qt5 and arabic text (#10436)
- // Note that both setFlags and the enums are undocumented
- tl.setFlags(rtl ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight);
- int const offset = 1;
#endif
+ int const offset = 1 + BIDI_OFFSET;
tl.setText(qs);
tl.setFont(font_);
--
lyx-cvs mailing list
[email protected]
http://lists.lyx.org/mailman/listinfo/lyx-cvs