Andre Poenitz wrote:
On Tue, Aug 22, 2006 at 10:44:21AM +0200, Abdelrazak Younes wrote:
I proposed to use ucs2 conditionally at compile time to avoid the above
conversion but Lars is furiously against that. I really don't know how
we are going to represent an ucs4 characters on screen with Qt4 so I
don't see the reason to use that. Or is there a way to do that?
UCS-4 -> UCS-2 conversion should not be noticable compared to displaying
the result on screen.
I thought also that it should be a matter of a simple cast from 4 to 2
bytes, thus ignoring the trailing two bytes (or the first two for big
endian systems). Actually I have been experimenting with that and it
appears that it works well.
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...
Try it :-)
Abdel.
Index: frontends/qt4/qfont_metrics.C
===================================================================
--- frontends/qt4/qfont_metrics.C (revision 14842)
+++ 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(QChar(static_cast<uint>(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(QChar(static_cast<uint>(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(QChar(static_cast<uint>(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 = toqstr(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 14842)
+++ 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 = toqstr(s, ls);
#endif
#if 0
Index: frontends/qt4/QLyXKeySym.C
===================================================================
--- frontends/qt4/QLyXKeySym.C (revision 14842)
+++ frontends/qt4/QLyXKeySym.C (working copy)
@@ -200,18 +200,22 @@
size_t QLyXKeySym::getUCSEncoded() const
{
- unsigned short const * ptr = text_.utf16();
- std::vector<unsigned short> tmp(ptr, ptr + text_.length());
+ // FIXME: Why do we need more than one char?
+ //BOOST_ASSERT(text_.size() == 1);
+ //return static_cast<boost::uint32_t>(text_[0].unicode());
- //lyxerr << "Data is " << tmp << endl;
- lyxerr << "Length is " << text_.length() << endl;
+ //static char_type * ucs4 = new char_type[1000];
+ char_type ucs4[4];
- if (text_.isEmpty())
- return 0;
+ lyxerr << "getUCSEncoded text_ size " << text_.size() << endl;
- //size_t res = utf8_to_ucs4(tmp, tmp.length());
- //lyxerr << "Res is " << res << endl;
- return ucs2_to_ucs4(tmp)[0];
+ size_t ls = text_.size();
+ for (size_t i = 0; i < ls; ++i)
+ ucs4[i] = static_cast<boost::uint32_t>(text_[i].unicode());
+
+ ucs4[ls] = 0;
+
+ return ucs4[0];
}
Index: frontends/qt4/qt_helpers.C
===================================================================
--- frontends/qt4/qt_helpers.C (revision 14842)
+++ 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>
@@ -32,6 +34,7 @@
using std::make_pair;
using std::string;
using std::pair;
+using std::endl;
string makeFontName(string const & family, string const & foundry)
@@ -114,6 +117,33 @@
}
+QString const toqstr(char_type const * str, size_t ls)
+{
+ QString s;
+
+ // 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...
+ for (size_t i = 0; i < ls; ++i)
+ s.append(QChar(static_cast<unsigned short>(str[i])));
+
+ return s;
+
+ // C-ish version in case the above doesn't work on Big endian
+ // systems.
+ // ENDIAN_OFFSET should be 0 on Little Endian systems and 2 on
+ // Big Endian systems.
+#define ENDIAN_OFFSET 0
+
+ char const * ptr = reinterpret_cast<char const *>(str);
+ char const * end_ptr = ptr + 4*ls;
+ for (; ptr < end_ptr; ptr += 4)
+ s.append(QChar(*(reinterpret_cast<unsigned short const *>(ptr +
ENDIAN_OFFSET))));
+
+ return s;
+}
+
+
QString const qt_(char const * str)
{
return toqstr(_(str));
Index: frontends/qt4/qt_helpers.h
===================================================================
--- frontends/qt4/qt_helpers.h (revision 14842)
+++ frontends/qt4/qt_helpers.h (working copy)
@@ -17,6 +17,10 @@
#include "lyxlength.h"
//#include "lengthcombo.h"
+#include "support/types.h"
+
+using lyx::char_type;
+
class LengthCombo;
class QComboBox;
class QLineEdit;
@@ -57,6 +61,14 @@
/**
+ * toqstr - convert ucs4 into QString
+ *
+ * QString uses ucs2 (a.k.a utf16) internally.
+ */
+QString const toqstr(char_type const * str, size_t ls);
+
+
+/**
* qt_ - i18nize string and convert to unicode
*
* Use this in qt4/ instead of qt_()