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

Reply via email to