mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-24 02:35:20 +00:00
Work around issues with Qt5 and Arabic text
This fixes two particular problems
* with Qt5, it seems that QFontMetrics::width does not return the
correct value for some Arabic text; this patch uses QTextLayout
instead to compute a string width
* Likewise, the undocumented layout flags TextForceRightToLeft and
TextForceLeftToRight do not work with Arabic text; this patch uses
unicode override characters instead.
It might be that the two issues are related. In any case, they do not
happen with latin text where right-to-left direction is enforced. And
they do not happen with Qt4.
Additionally, remove some dead code in GuiFontMetrics::pos2x().
Fixes bug #10436.
(cherry picked from commit e832d2e90f
)
This commit is contained in:
parent
10b8421ed6
commit
24648404b3
@ -146,7 +146,16 @@ int GuiFontMetrics::width(docstring const & s) const
|
|||||||
int * pw = strwidth_cache_[qba];
|
int * pw = strwidth_cache_[qba];
|
||||||
if (pw)
|
if (pw)
|
||||||
return *pw;
|
return *pw;
|
||||||
int w = metrics_.width(toqstr(s));
|
// For some reason QMetrics::width returns a wrong value with Qt5
|
||||||
|
// int w = metrics_.width(toqstr(s));
|
||||||
|
QTextLayout tl;
|
||||||
|
tl.setText(toqstr(s));
|
||||||
|
tl.setFont(font_);
|
||||||
|
tl.beginLayout();
|
||||||
|
QTextLine line = tl.createLine();
|
||||||
|
tl.endLayout();
|
||||||
|
int w = int(line.naturalTextWidth());
|
||||||
|
|
||||||
strwidth_cache_.insert(qba, new int(w), qba.size());
|
strwidth_cache_.insert(qba, new int(w), qba.size());
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
@ -196,8 +205,6 @@ GuiFontMetrics::getTextLayout(docstring const & s, QFont font,
|
|||||||
int GuiFontMetrics::pos2x(docstring const & s, int const pos, bool const rtl,
|
int GuiFontMetrics::pos2x(docstring const & s, int const pos, bool const rtl,
|
||||||
double const wordspacing) const
|
double const wordspacing) const
|
||||||
{
|
{
|
||||||
QFont copy = font_;
|
|
||||||
copy.setWordSpacing(wordspacing);
|
|
||||||
QTextLayout const & tl = getTextLayout(s, font_, rtl, wordspacing);
|
QTextLayout const & tl = getTextLayout(s, font_, rtl, wordspacing);
|
||||||
return static_cast<int>(tl.lineForTextPosition(pos).cursorToX(pos));
|
return static_cast<int>(tl.lineForTextPosition(pos).cursorToX(pos));
|
||||||
}
|
}
|
||||||
@ -228,10 +235,27 @@ bool GuiFontMetrics::breakAt(docstring & s, int & x, bool const rtl, bool const
|
|||||||
*/
|
*/
|
||||||
// Unicode character ZERO WIDTH NO-BREAK SPACE
|
// Unicode character ZERO WIDTH NO-BREAK SPACE
|
||||||
QChar const zerow_nbsp(0xfeff);
|
QChar const zerow_nbsp(0xfeff);
|
||||||
tl.setText(zerow_nbsp + toqstr(s) + zerow_nbsp);
|
QString str = zerow_nbsp + toqstr(s) + zerow_nbsp;
|
||||||
tl.setFont(font_);
|
#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
|
||||||
|
str = QChar(0x202E) + str;
|
||||||
|
else
|
||||||
|
// Left-to-right override: forces to draw text left-to-right
|
||||||
|
str = QChar(0x202D) + str;
|
||||||
|
int const offset = 2;
|
||||||
|
#else
|
||||||
|
// Alternative version that breaks with Qt5 and arabic text (#10436)
|
||||||
// Note that both setFlags and the enums are undocumented
|
// Note that both setFlags and the enums are undocumented
|
||||||
tl.setFlags(rtl ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight);
|
tl.setFlags(rtl ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight);
|
||||||
|
int const offset = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tl.setText(str);
|
||||||
|
tl.setFont(font_);
|
||||||
QTextOption to;
|
QTextOption to;
|
||||||
to.setWrapMode(force ? QTextOption::WrapAnywhere : QTextOption::WordWrap);
|
to.setWrapMode(force ? QTextOption::WrapAnywhere : QTextOption::WordWrap);
|
||||||
tl.setTextOption(to);
|
tl.setTextOption(to);
|
||||||
@ -240,11 +264,11 @@ bool GuiFontMetrics::breakAt(docstring & s, int & x, bool const rtl, bool const
|
|||||||
line.setLineWidth(x);
|
line.setLineWidth(x);
|
||||||
tl.createLine();
|
tl.createLine();
|
||||||
tl.endLayout();
|
tl.endLayout();
|
||||||
if ((force && line.textLength() == 1) || int(line.naturalTextWidth()) > x)
|
if ((force && line.textLength() == offset) || int(line.naturalTextWidth()) > x)
|
||||||
return false;
|
return false;
|
||||||
x = int(line.naturalTextWidth());
|
x = int(line.naturalTextWidth());
|
||||||
// The -1 is here to account for the leading zerow_nbsp.
|
// The offset is here to account for the extra leading characters.
|
||||||
s = s.substr(0, line.textLength() - 1);
|
s = s.substr(0, line.textLength() - offset);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user