Abdelrazak Younes wrote:
In this patch I use simple casts instead of the costly ucs2_to_ucs4 and
ucs4_to_ucs2 functions. It turned out that all display issues are
resolved... including math! It even brings a very nice speed-up...
Here is a cleaned up version of the patch.
Some dialogs (labels insertion and TOC) still need to be updated with
the proper conversion methods.
Opinions?
Lars, if your not happy with my cast solution, we can still use your
ucs4_to_ucs2() and ucs2_to_ucs4() functions in ucs4_to_qchar() and
qchar_to_ucs4() later on.
But IMHO, there is really not need to use iconv for these simple
conversions. I even think that we should do the ucs4 to/from utf8
ourselves... it looks pretty simple from a first glance.
Abdel.
Index: frontends/qt4/qfont_metrics.C
===================================================================
--- frontends/qt4/qfont_metrics.C (revision 14849)
+++ frontends/qt4/qfont_metrics.C (working copy)
@@ -16,6 +16,7 @@
#include "Application.h"
#include "FontLoader.h"
+#include "qt_helpers.h"
#include "language.h"
@@ -29,7 +30,7 @@
namespace {
-int smallcapswidth(unsigned short const * s, size_t ls, LyXFont const & f)
+int smallcapswidth(QString const & s, LyXFont const & f)
{
if (!lyx_gui::use_gui)
return 1;
@@ -43,8 +44,10 @@
int w = 0;
+ size_t const ls = s.size();
+
for (size_t i = 0; i < ls; ++i) {
- QChar const c = s[i];
+ QChar const & c = s[i];
QChar const uc = c.toUpper();
if (c != uc)
w += qsmallm.width(uc);
@@ -80,7 +83,7 @@
{
if (!lyx_gui::use_gui)
return 1;
- QRect const & r =
theApp->fontLoader().metrics(f).boundingRect(ucs4_to_ucs2(c));
+ QRect const & r =
theApp->fontLoader().metrics(f).boundingRect(ucs4_to_qchar(c));
// Qt/Win 3.2.1nc (at least) corrects the GetGlyphOutlineA|W y
// value by the height: (x, -y-height, width, height).
// Other versions return: (x, -y, width, height)
@@ -96,7 +99,7 @@
{
if (!lyx_gui::use_gui)
return 1;
- QRect const & r =
theApp->fontLoader().metrics(f).boundingRect(ucs4_to_ucs2(c));
+ QRect const & r =
theApp->fontLoader().metrics(f).boundingRect(ucs4_to_qchar(c));
// Qt/Win 3.2.1nc (at least) corrects the GetGlyphOutlineA|W y
// value by the height: (x, -y-height, width, height).
// Other versions return: (x, -y, width, height)
@@ -112,7 +115,7 @@
{
if (!lyx_gui::use_gui)
return 1;
- return theApp->fontLoader().metrics(f).leftBearing(ucs4_to_ucs2(c));
+ return theApp->fontLoader().metrics(f).leftBearing(ucs4_to_qchar(c));
}
@@ -123,7 +126,7 @@
QFontMetrics const & m = theApp->fontLoader().metrics(f);
// Qt rbearing is from the right edge of the char's width().
- unsigned short sc = ucs4_to_ucs2(c);
+ QChar sc(static_cast<uint>(c));
return m.width(sc) - m.rightBearing(sc);
}
@@ -133,20 +136,19 @@
if (!lyx_gui::use_gui)
return ls;
- std::vector<unsigned short> ucs2 = ucs4_to_ucs2(s, ls);
- ucs2.push_back(0);
+ QString ucs2 = ucs4_to_qstring(s, ls);
if (f.realShape() == LyXFont::SMALLCAPS_SHAPE)
- return smallcapswidth(&ucs2[0], ls, f);
+ return smallcapswidth(ucs2, f);
QLFontInfo & fi = theApp->fontLoader().fontinfo(f);
if (ls == 1)
- return fi.width(ucs2[0]);
+ return fi.width(ucs2[0].unicode());
int w = 0;
for (size_t i = 0; i < ls; ++i)
- w += fi.width(ucs2[i]);
+ w += fi.width(ucs2[i].unicode());
return w;
}
Index: frontends/qt4/QLPainter.C
===================================================================
--- frontends/qt4/QLPainter.C (revision 14849)
+++ frontends/qt4/QLPainter.C (working copy)
@@ -19,6 +19,7 @@
#include "FontLoader.h"
#include "Application.h"
+#include "qt_helpers.h"
#include "debug.h"
#include "language.h"
@@ -239,11 +240,7 @@
for (unsigned int i = 0; i < ls; ++i)
str[i] = QChar(encoding->ucs(s[i]));
#else
- //std::vector<boost::uint32_t> in(s, s + ls);
- //std::vector<unsigned short> ucs2 = ucs4_to_ucs2(in);
- std::vector<unsigned short> ucs2 = ucs4_to_ucs2(s, ls);
- ucs2.push_back(0);
- QString str = QString::fromUtf16(&ucs2[0]);
+ QString str = ucs4_to_qstring(s, ls);
#endif
#if 0
Index: frontends/qt4/QLyXKeySym.C
===================================================================
--- frontends/qt4/QLyXKeySym.C (revision 14849)
+++ frontends/qt4/QLyXKeySym.C (working copy)
@@ -200,18 +200,11 @@
size_t QLyXKeySym::getUCSEncoded() const
{
- unsigned short const * ptr = text_.utf16();
- std::vector<unsigned short> tmp(ptr, ptr + text_.length());
+ if (text_.isEmpty())
+ return 0;
- //lyxerr << "Data is " << tmp << endl;
- lyxerr << "Length is " << text_.length() << endl;
-
- if (text_.isEmpty())
- return 0;
-
- //size_t res = utf8_to_ucs4(tmp, tmp.length());
- //lyxerr << "Res is " << res << endl;
- return ucs2_to_ucs4(tmp)[0];
+ BOOST_ASSERT(text_.size() == 1);
+ return qchar_to_ucs4(text_[0]);
}
Index: frontends/qt4/qt_helpers.C
===================================================================
--- frontends/qt4/qt_helpers.C (revision 14849)
+++ frontends/qt4/qt_helpers.C (working copy)
@@ -20,6 +20,8 @@
#include "support/lstrings.h"
#include "support/convert.h"
+#include "debug.h"
+
#include <QComboBox>
#include <qlineedit.h>
#include <qtextcodec.h>
@@ -28,10 +30,13 @@
using lyx::support::isStrDbl;
+using lyx::char_type;
+using std::vector;
using std::make_pair;
using std::string;
using std::pair;
+using std::endl;
string makeFontName(string const & family, string const & foundry)
@@ -114,6 +119,76 @@
}
+QString const ucs4_to_qstring(char_type const * str, size_t ls)
+{
+ QString s;
+
+ for (size_t i = 0; i < ls; ++i)
+ s.append(ucs4_to_qchar(str[i]));
+
+ return s;
+}
+
+
+QString const ucs4_to_qstring(vector<char_type> const & ucs4)
+{
+ QString s;
+ size_t const ls = ucs4.size();
+
+ for (size_t i = 0; i < ls; ++i)
+ s.append(ucs4_to_qchar(ucs4[i]));
+
+ return s;
+}
+
+
+vector<char_type> qstring_to_ucs4(QString const & qstr)
+{
+ size_t ls = qstr.size();
+ vector<char_type> ucs4;
+ for (size_t i = 0; i < ls; ++i)
+ ucs4.push_back(static_cast<boost::uint32_t>(qstr[i].unicode()));
+
+ return ucs4;
+}
+
+
+void qstring_to_ucs4(QString const & qstr, vector<char_type> & ucs4)
+{
+ size_t ls = qstr.size();
+ ucs4.clear();
+ for (size_t i = 0; i < ls; ++i)
+ ucs4.push_back(static_cast<boost::uint32_t>(qstr[i].unicode()));
+}
+
+
+char_type const qchar_to_ucs4(QChar const & qchar)
+{
+ return static_cast<boost::uint32_t>(qchar.unicode());
+}
+
+
+QChar const ucs4_to_qchar(char_type const & ucs4)
+{
+ // This version works fine with Little Endian systems (PC)
+ // If a need to split up the ucs4 and use the other part of it
+ // we will need the C-ish version below... so just comment out
+ // the following line:
+ return QChar(static_cast<unsigned short>(ucs4));
+
+ // C-ish version in case the above doesn't work on Big endian
+ // systems.
+ // ENDIAN_OFFSET should be 0 on Little Endian systems and 1 on
+ // Big Endian systems.
+#define ENDIAN_OFFSET 0
+
+ unsigned short const * ptr =
+ reinterpret_cast<unsigned short const *>(&ucs4);
+
+ return QChar(*(ptr + ENDIAN_OFFSET));
+}
+
+
QString const qt_(char const * str)
{
return toqstr(_(str));
Index: frontends/qt4/qt_helpers.h
===================================================================
--- frontends/qt4/qt_helpers.h (revision 14849)
+++ frontends/qt4/qt_helpers.h (working copy)
@@ -17,10 +17,15 @@
#include "lyxlength.h"
//#include "lengthcombo.h"
+#include "support/types.h"
+
+#include <vector>
+
class LengthCombo;
class QComboBox;
class QLineEdit;
class QString;
+class QChar;
std::string makeFontName(std::string const & family, std::string const &
foundry);
@@ -57,6 +62,24 @@
/**
+ * toqstr - convert ucs4 into QString
+ *
+ * QString uses ucs2 (a.k.a utf16) internally.
+ */
+QString const ucs4_to_qstring(lyx::char_type const * str, size_t ls);
+
+QString const ucs4_to_qstring(std::vector<lyx::char_type> const & ucs4);
+
+std::vector<lyx::char_type> qstring_to_ucs4(QString const & qstr);
+
+void qstring_to_ucs4(QString const & qstr, std::vector<lyx::char_type> & ucs4);
+
+lyx::char_type const qchar_to_ucs4(QChar const & qchar);
+
+QChar const ucs4_to_qchar(lyx::char_type const & ucs4);
+
+
+/**
* qt_ - i18nize string and convert to unicode
*
* Use this in qt4/ instead of qt_()