The branch, str-metrics, has been updated. - Log -----------------------------------------------------------------
commit 86c4d53087e99f0c8714cac88ccd950ff6666581 Author: Jean-Marc <lasgout...@lyx.org> Date: Mon Jul 21 00:19:50 2014 +0200 Better algorithm for forcing bidi drawing The use of RLO/LRO overrides to force text orientation did not work properly on MacOSX where some characters got dropped. This new approach is much cleaner, except that it relies on features not advertised in documentation but present at least from Qt 4.5 to Qt 5.3: * TextFlag enum values TextForceLeftToRight and TextForceRightToLeft, which are strong versions of QPainter::setLayoutDirection; they are passed as a parameter of QPainter::drawText. * QTextLayout::setFlags method, which is required to pass the above flags to QTextLayout. diff --git a/src/frontends/Painter.h b/src/frontends/Painter.h index 3302d16..78ec6e5 100644 --- a/src/frontends/Painter.h +++ b/src/frontends/Painter.h @@ -109,10 +109,10 @@ public: graphics::Image const & image) = 0; /** draw a string at position x, y (y is the baseline). The - * text direction is deduced from \c str. + * text direction is given by \c rtl. * \return the width of the drawn text. */ - virtual int text(int x, int y, docstring const & str, FontInfo const & f) = 0; + virtual int text(int x, int y, docstring const & str, FontInfo const & f, bool rtl = false) = 0; /** draw a string at position x, y (y is the baseline). The * text direction is enforced by the \c Font. diff --git a/src/frontends/qt4/GuiFontMetrics.cpp b/src/frontends/qt4/GuiFontMetrics.cpp index 492a0a9..6952e96 100644 --- a/src/frontends/qt4/GuiFontMetrics.cpp +++ b/src/frontends/qt4/GuiFontMetrics.cpp @@ -22,7 +22,6 @@ #include "insets/Inset.h" #include "support/lassert.h" -#include "support/lstrings.h" #include <QTextLayout> @@ -148,9 +147,10 @@ namespace { void setTextLayout(QTextLayout & tl, docstring const & s, QFont const & font, bool const rtl) { - QString const qs = toqstr(directedString(s, rtl)); - tl.setText(qs); + tl.setText(toqstr(s)); tl.setFont(font); + // Note that both setFlags and the enums are undocumented + tl.setFlags(rtl ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight); tl.beginLayout(); tl.createLine(); tl.endLayout(); @@ -162,8 +162,7 @@ int GuiFontMetrics::pos2x(docstring const & s, int const pos, bool const rtl) co { QTextLayout tl; setTextLayout(tl, s, font_, rtl); - // we take into account the unicode formatting characters - return tl.lineForTextPosition(pos + 1).cursorToX(pos + 1); + return tl.lineForTextPosition(pos).cursorToX(pos); } @@ -172,13 +171,8 @@ int GuiFontMetrics::x2pos(docstring const & s, int & x, bool const rtl) const QTextLayout tl; setTextLayout(tl, s, font_, rtl); int pos = tl.lineForTextPosition(0).xToCursor(x); - // take into account the unicode formatting characters - if (pos > 0) - --pos; - if (pos > int(s.length())) - pos = s.length(); // correct x value to the actual cursor position. - x = tl.lineForTextPosition(0).cursorToX(pos + 1); + x = tl.lineForTextPosition(0).cursorToX(pos); return pos; } diff --git a/src/frontends/qt4/GuiPainter.cpp b/src/frontends/qt4/GuiPainter.cpp index 2b51f47..6450d58 100644 --- a/src/frontends/qt4/GuiPainter.cpp +++ b/src/frontends/qt4/GuiPainter.cpp @@ -27,7 +27,6 @@ #include "insets/Inset.h" #include "support/lassert.h" -#include "support/lstrings.h" #include "support/debug.h" #include <QPixmapCache> @@ -278,7 +277,7 @@ int GuiPainter::text(int x, int y, char_type c, FontInfo const & f) int GuiPainter::text(int x, int y, docstring const & s, - FontInfo const & f) + FontInfo const & f, bool const rtl) { //LYXERR0("text: x=" << x << ", s=" << s); if (s.empty()) @@ -304,8 +303,8 @@ int GuiPainter::text(int x, int y, docstring const & s, str = ' ' + str; #endif - QFont const & ff = getFont(f); - GuiFontMetrics const & fm = getFontMetrics(f); + QFont const & ff = getFont(f); + GuiFontMetrics const & fm = getFontMetrics(f); // Here we use the font width cache instead of // textwidth = fontMetrics().width(str); @@ -390,7 +389,12 @@ int GuiPainter::text(int x, int y, docstring const & s, setQPainterPen(computeColor(f.realColor())); if (font() != ff) setFont(ff); - drawText(x, y, str); + //This is much stronger than setLayoutDirection (but + //unfortunately it is undocumented). + int flag = rtl ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight; + drawText(x + (rtl ? textwidth : 0), y - fm.maxAscent(), 0, 0, + flag | Qt::TextDontClip, + str); //LYXERR(Debug::PAINTING, "draw " << string(str.toUtf8()) // << " at " << x << "," << y); return textwidth; @@ -399,8 +403,7 @@ int GuiPainter::text(int x, int y, docstring const & s, int GuiPainter::text(int x, int y, docstring const & str, Font const & f) { - docstring const dstr = directedString(str, f.isVisibleRightToLeft()); - return text(x, y, dstr, f.fontInfo()); + return text(x, y, str, f.fontInfo(), f.isVisibleRightToLeft()); } @@ -410,7 +413,6 @@ int GuiPainter::text(int x, int y, docstring const & str, Font const & f, GuiFontMetrics const & fm = getFontMetrics(f.fontInfo()); FontInfo fi = f.fontInfo(); bool const rtl = f.isVisibleRightToLeft(); - docstring const dstr = directedString(str, rtl); // dimensions int const ascent = fm.maxAscent(); @@ -424,15 +426,15 @@ int GuiPainter::text(int x, int y, docstring const & str, Font const & f, Color const orig = fi.realColor(); fi.setPaintColor(other); setClipRect(QRect(x + xmin, y - ascent, xmax - xmin, height)); - int const textwidth = text(x, y, dstr, fi); + int const textwidth = text(x, y, str, fi, rtl); // Then the part in normal color // Note that in Qt5, it is not possible to use Qt::UniteClip fi.setPaintColor(orig); setClipRect(QRect(x, y - ascent, xmin, height)); - text(x, y, dstr, fi); + text(x, y, str, fi, rtl); setClipRect(QRect(x + xmax, y - ascent, textwidth - xmax, height)); - text(x, y, dstr, fi); + text(x, y, str, fi, rtl); setClipping(false); return textwidth; diff --git a/src/frontends/qt4/GuiPainter.h b/src/frontends/qt4/GuiPainter.h index a3ac38c..3af5175 100644 --- a/src/frontends/qt4/GuiPainter.h +++ b/src/frontends/qt4/GuiPainter.h @@ -87,10 +87,10 @@ public: lyx::graphics::Image const & image); /** draw a string at position x, y (y is the baseline). The - * text direction is deduced from \c str. + * text direction is given by \c rtl. * \return the width of the drawn text. */ - virtual int text(int x, int y, docstring const & str, FontInfo const & f); + virtual int text(int x, int y, docstring const & str, FontInfo const & f, bool rtl = false); /** draw a string at position x, y (y is the baseline). The * text direction is enforced by the \c Font. diff --git a/src/support/lstrings.cpp b/src/support/lstrings.cpp index cec1812..8508e4e 100644 --- a/src/support/lstrings.cpp +++ b/src/support/lstrings.cpp @@ -1502,23 +1502,5 @@ docstring bformat(docstring const & fmt, return subst(str, from_ascii("%%"), from_ascii("%")); } - -docstring directedString(docstring const & s, bool const rtl) -{ - /* In LyX, the character direction is forced by the language. - * Therefore, we have to signal that fact to Qt. - * Source: http://www.iamcal.com/understanding-bidirectional-text/ - */ - // Left-to-right override: forces to draw text left-to-right - char_type const LRO = 0x202D; - // Right-to-left override: forces to draw text right-to-left - char_type const RLO = 0x202E; - // Pop directional formatting: return to previous state - char_type const PDF = 0x202C; - return (rtl ? RLO : LRO) + s + PDF; -} - - - } // namespace support } // namespace lyx diff --git a/src/support/lstrings.h b/src/support/lstrings.h index 6fb1daf..0d21e95 100644 --- a/src/support/lstrings.h +++ b/src/support/lstrings.h @@ -327,9 +327,6 @@ template<> docstring bformat(docstring const & fmt, int arg1, int arg2); template<> docstring bformat(docstring const & fmt, docstring arg1, docstring arg2, docstring arg3); template<> docstring bformat(docstring const & fmt, docstring arg1, docstring arg2, docstring arg3, docstring arg4); -/// Return a string with Unicode overrides to enforce the writing direction -docstring directedString(docstring const & s, bool rtl); - } // namespace support } // namespace lyx ----------------------------------------------------------------------- Summary of changes: src/frontends/Painter.h | 4 ++-- src/frontends/qt4/GuiFontMetrics.cpp | 16 +++++----------- src/frontends/qt4/GuiPainter.cpp | 24 +++++++++++++----------- src/frontends/qt4/GuiPainter.h | 4 ++-- src/support/lstrings.cpp | 18 ------------------ src/support/lstrings.h | 3 --- 6 files changed, 22 insertions(+), 47 deletions(-) hooks/post-receive -- Repository for new features