From f8175cca5eaf70bfdf5daa745afe5821d9ce9e6a Mon Sep 17 00:00:00 2001 From: Abdelrazak Younes Date: Thu, 31 May 2007 12:48:42 +0000 Subject: [PATCH] This commit allows to support the full unicode range in GuiFontMetrics thus fixing the crash in this bug: http://bugzilla.lyx.org/show_bug.cgi?id=3759 It also simplifies and fix the smallcaps case which was not correct WRT unicode. Even though I don't know if toUpper() means something in the non ucs2 range. FYI, I used toqstr() to do the ucs4 -> ucs2 conversion when needed. This helper method works only with Qt >= 4.2. * GuiFontMetrics::smallcapsWidth(): changed to work with single ucs4 characters. * GuiFontMetrics::xxx(): make sure that font metrics works with characters not in the ucs2 range. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@18593 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/frontends/qt4/GuiFontMetrics.cpp | 86 ++++++++++++++-------------- src/frontends/qt4/GuiFontMetrics.h | 2 +- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/frontends/qt4/GuiFontMetrics.cpp b/src/frontends/qt4/GuiFontMetrics.cpp index 7737b944f9..d9e1348613 100644 --- a/src/frontends/qt4/GuiFontMetrics.cpp +++ b/src/frontends/qt4/GuiFontMetrics.cpp @@ -53,6 +53,12 @@ int GuiFontMetrics::maxDescent() const int GuiFontMetrics::lbearing(char_type c) const { + if (!is_utf16(c)) + // FIXME: QFontMetrics::leftBearingdoes not support the + // full unicode range. Once it does, we could use: + //return metrics_.leftBearing(toqstr(docstring(1,c))); + return 0; + return metrics_.leftBearing(ucs4_to_qchar(c)); } @@ -61,48 +67,46 @@ int GuiFontMetrics::rbearing(char_type c) const { if (!rbearing_cache_.contains(c)) { // Qt rbearing is from the right edge of the char's width(). - QChar sc = ucs4_to_qchar(c); - int rb = metrics_.width(sc) - metrics_.rightBearing(sc); + int rb; + if (is_utf16(c)) { + QChar sc = ucs4_to_qchar(c); + rb = width(c) - metrics_.rightBearing(sc); + } else + // FIXME: QFontMetrics::leftBearingdoes not support the + // full unicode range. Once it does, we could use: + // metrics_.rightBearing(toqstr(docstring(1,c))); + rb = width(c); + rbearing_cache_.insert(c, rb); } return rbearing_cache_.value(c); } -int GuiFontMetrics::smallcapsWidth(QString const & s) const +int GuiFontMetrics::smallcapsWidth(char_type c) const { - int w = 0; - int const ls = s.size(); - - for (int i = 0; i < ls; ++i) { - QChar const & c = s[i]; - QChar const uc = c.toUpper(); - if (c != uc) - w += smallcaps_metrics_.width(uc); + // FIXME: Optimisation probably needed: we don't use the width cache. + if (is_utf16(c)) { + QChar const qc = ucs4_to_qchar(c); + QChar const uc = qc.toUpper(); + if (qc != uc) + return smallcaps_metrics_.width(uc); + else + return metrics_.width(qc); + } else { + QString const s = toqstr(docstring(1,c)); + QString const us = s.toUpper(); + if (s != us) + return smallcaps_metrics_.width(us); else - w += metrics_.width(c); + return metrics_.width(s); } - return w; } int GuiFontMetrics::width(docstring const & s) const { size_t ls = s.size(); - if (ls == 0) - return 0; - - if (ls == 1 && !smallcaps_shape_) { - return width(s[0]); - } - - if (smallcaps_shape_) - // Caution: The following ucs4 to QString conversions work - // for symbol fonts only because they are no real conversions - // but simple casts in reality. See comment in QLPainter::text() - // for more explanation. - return smallcapsWidth(toqstr(s)); - int w = 0; for (unsigned int i = 0; i < ls; ++i) w += width(s[i]); @@ -113,19 +117,7 @@ int GuiFontMetrics::width(docstring const & s) const int GuiFontMetrics::width(QString const & ucs2) const { - int const ls = ucs2.size(); - if (ls == 1 && !smallcaps_shape_) { - return width(ucs2[0].unicode()); - } - - if (smallcaps_shape_) - return smallcapsWidth(ucs2); - - int w = 0; - for (int i = 0; i < ls; ++i) - w += width(ucs2[i].unicode()); - - return w; + return width(qstring_to_ucs4(ucs2)); } @@ -176,7 +168,12 @@ Dimension const GuiFontMetrics::dimension(char_type c) const void GuiFontMetrics::fillMetricsCache(char_type c) const { - QRect const & r = metrics_.boundingRect(ucs4_to_qchar(c)); + QRect r; + if (is_utf16(c)) + r = metrics_.boundingRect(ucs4_to_qchar(c)); + else + r = metrics_.boundingRect(toqstr(docstring(1,c))); + AscendDescend ad = { -r.top(), r.bottom() + 1}; // We could as well compute the width but this is not really // needed for now as it is done directly in width() below. @@ -187,10 +184,13 @@ void GuiFontMetrics::fillMetricsCache(char_type c) const int GuiFontMetrics::width(char_type c) const { if (smallcaps_shape_) - return smallcapsWidth(ucs4_to_qchar(c)); + return smallcapsWidth(c); if (!width_cache_.contains(c)) { - width_cache_.insert(c, metrics_.width(ucs4_to_qchar(c))); + if (is_utf16(c)) + width_cache_.insert(c, metrics_.width(ucs4_to_qchar(c))); + else + width_cache_.insert(c, metrics_.width(toqstr(docstring(1,c)))); } return width_cache_.value(c); diff --git a/src/frontends/qt4/GuiFontMetrics.h b/src/frontends/qt4/GuiFontMetrics.h index fc071f2684..d4c0786164 100644 --- a/src/frontends/qt4/GuiFontMetrics.h +++ b/src/frontends/qt4/GuiFontMetrics.h @@ -56,7 +56,7 @@ public: int width(QString const & str) const; private: - int smallcapsWidth(QString const & s) const; + int smallcapsWidth(char_type c) const; /// Metrics on the font QFontMetrics metrics_; -- 2.39.2