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_()

Reply via email to