Abdelrazak Younes wrote: > 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 :-) >
I've tested it under Windows and Linux and the patch fixes all the display issues, great. > 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))); Maybe it is worth to define a inline function in qt_helpers: QChar const & ucs4_to_QChar(char_type c) { return QChar(static_cast<uint>(c)); } then QChar(static_cast<uint>(c)) could be replaced with a more verbose code ucs4_to_QChar(c). The const is to avoid the copying. > // 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 > { should the return type not be a char_type? > - 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]; > Why do you need 4 char_types for one character? Only ucs4[0] is returned. > - 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; > +} > + > + Could the code not been switched by a macro? > 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_()