From d0b8f24cc262a8dd69254a6097b4c0be1254dd50 Mon Sep 17 00:00:00 2001 From: Abdelrazak Younes Date: Mon, 27 Aug 2007 11:10:28 +0000 Subject: [PATCH] Backport the pixmap cache from trunk. Disabled for X11 and for Qt < 4.2 git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_1_5_X@19829 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/frontends/qt4/GuiApplication.cpp | 5 + src/frontends/qt4/QLPainter.cpp | 134 +++++++++++++++++++++------ status.15x | 6 +- 3 files changed, 114 insertions(+), 31 deletions(-) diff --git a/src/frontends/qt4/GuiApplication.cpp b/src/frontends/qt4/GuiApplication.cpp index 4b3ed3e9c8..a4a9df859f 100644 --- a/src/frontends/qt4/GuiApplication.cpp +++ b/src/frontends/qt4/GuiApplication.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -149,6 +150,10 @@ GuiApplication::GuiApplication(int & argc, char ** argv) LoaderQueue::setPriority(10,100); guiApp = this; + + // Set the cache to 5120 kilobytes which corresponds to screen size of + // 1280 by 1024 pixels with a color depth of 32 bits. + QPixmapCache::setCacheLimit(5120); } diff --git a/src/frontends/qt4/QLPainter.cpp b/src/frontends/qt4/QLPainter.cpp index 4ed39cbdae..d290f48b21 100644 --- a/src/frontends/qt4/QLPainter.cpp +++ b/src/frontends/qt4/QLPainter.cpp @@ -11,8 +11,6 @@ #include -#include - #include "QLPainter.h" #include "GuiApplication.h" @@ -28,12 +26,40 @@ #include "support/unicode.h" +#include +#include + +// Set USE_PIXMAP_CACHE to 1 for enabling the use of a Pixmap cache when +// drawing text. This is especially useful for older PPC/Mac systems. +#if (QT_VERSION < 0x040200) || defined(Q_WS_X11) +#define USE_PIXMAP_CACHE 0 +#else +#define USE_PIXMAP_CACHE 1 +#endif + using std::endl; using std::string; namespace lyx { namespace frontend { +namespace { + +bool const usePixmapCache = USE_PIXMAP_CACHE; + +QString generateStringSignature(QString const & str, Font const & f) +{ + QString sig = str; + sig.append(QChar(static_cast(f.family()))); + sig.append(QChar(static_cast(f.series()))); + sig.append(QChar(static_cast(f.realShape()))); + sig.append(QChar(static_cast(f.size()))); + sig.append(QChar(static_cast(f.color()))); + return sig; +} + +} // anon namespace + QLPainter::QLPainter(QPaintDevice * device) : QPainter(device), Painter() { @@ -243,42 +269,90 @@ int QLPainter::text(int x, int y, docstring const & s, int textwidth; - if (f.realShape() != Font::SMALLCAPS_SHAPE) { + if (f.realShape() == Font::SMALLCAPS_SHAPE) { + textwidth = smallCapsText(x, y, str, f); + if (f.underbar() == Font::ON) + underline(f, x, y, textwidth); + return textwidth; + } + + // Here we use the font width cache instead of + // textwidth = fontMetrics().width(str); + // because the above is awfully expensive on MacOSX + textwidth = fi.metrics->width(s); + if (f.underbar() == Font::ON) + underline(f, x, y, textwidth); + + if (!isDrawingEnabled()) + return textwidth; + + // Qt4 does not display a glyph whose codepoint is the + // same as that of a soft-hyphen (0x00ad), unless it + // occurs at a line-break. As a kludge, we force Qt to + // render this glyph using a one-column line. + if (s.size() == 1 && str[0].unicode() == 0x00ad) { + setQPainterPen(f.realColor()); + QTextLayout adsymbol(str); + adsymbol.setFont(fi.font); + adsymbol.beginLayout(); + QTextLine line = adsymbol.createLine(); + line.setNumColumns(1); + line.setPosition(QPointF(0, -line.ascent())); + adsymbol.endLayout(); + line.draw(this, QPointF(x, y)); + return textwidth; + } + + if (!usePixmapCache) { + // don't use the pixmap cache, + // draw directly onto the painting device setQPainterPen(f.realColor()); if (font() != fi.font) setFont(fi.font); // We need to draw the text as LTR as we use our own bidi code. setLayoutDirection(Qt::LeftToRight); - if (isDrawingEnabled()) { - LYXERR(Debug::PAINTING) << "draw " << std::string(str.toUtf8()) - << " at " << x << "," << y << std::endl; - // Qt4 does not display a glyph whose codepoint is the - // same as that of a soft-hyphen (0x00ad), unless it - // occurs at a line-break. As a kludge, we force Qt to - // render this glyph using a one-column line. - if (s.size() == 1 && str[0].unicode() == 0x00ad) { - QTextLayout adsymbol(str); - adsymbol.setFont(fi.font); - adsymbol.beginLayout(); - QTextLine line = adsymbol.createLine(); - line.setNumColumns(1); - line.setPosition(QPointF(0, -line.ascent())); - adsymbol.endLayout(); - line.draw(this, QPointF(x, y)); - } else - drawText(x, y, str); - } - // Here we use the font width cache instead of - // textwidth = fontMetrics().width(str); - // because the above is awfully expensive on MacOSX - textwidth = fi.metrics->width(str); - } else { - textwidth = smallCapsText(x, y, str, f); + // We need to draw the text as LTR as we use our own bidi code. + setLayoutDirection(Qt::LeftToRight); + drawText(x, y, str); + LYXERR(Debug::PAINTING) << "draw " << std::string(str.toUtf8()) + << " at " << x << "," << y << std::endl; + return textwidth; } - if (f.underbar() == Font::ON) { - underline(f, x, y, textwidth); + QPixmap pm; + QString key = generateStringSignature(str, f); + // Warning: Left bearing is in general negative! Only the case + // where left bearing is negative is of interest WRT the the + // pixmap width and the text x-position. + // Only the left bearing of the first character is important + // as we always write from left to right, even for + // right-to-left languages. + int const lb = std::min(fi.metrics->lbearing(s[0]), 0); + int const mA = fi.metrics->maxAscent(); + if (!QPixmapCache::find(key, pm)) { + // Only the right bearing of the last character is + // important as we always write from left to right, + // even for right-to-left languages. + int const rb = fi.metrics->rbearing(s[s.size()-1]); + int const w = textwidth + rb - lb; + int const mD = fi.metrics->maxDescent(); + int const h = mA + mD; + pm = QPixmap(w, h); + pm.fill(Qt::transparent); + QLPainter p(&pm); + p.setQPainterPen(f.realColor()); + if (p.font() != fi.font) + p.setFont(fi.font); + // We need to draw the text as LTR as we use our own bidi code. + p.setLayoutDirection(Qt::LeftToRight); + p.drawText(-lb, mA, str); + QPixmapCache::insert(key, pm); + LYXERR(Debug::PAINTING) << "h=" << h << " mA=" << mA << " mD=" << mD + << " w=" << w << " lb=" << lb << " tw=" << textwidth + << " rb=" << rb << endl; } + // Draw the cached pixmap. + drawPixmap(x + lb, y - mA, pm); return textwidth; } diff --git a/status.15x b/status.15x index 15c636a497..46f00ac14c 100644 --- a/status.15x +++ b/status.15x @@ -52,7 +52,9 @@ What's new - Add "Save all on log-out or cancel" feature (Bug 1656). -- Fix crash when inserting float. +- Add a pixmap cache to speed up text drawing on screen. This cache is + enabled on Mac and Windows platform using a version of Qt greater + than 4.2. ** Bug fixes: @@ -100,6 +102,8 @@ What's new - Fix crash when login out from within Gnome desktop (Bug 1656). +- Fix crash when inserting float. + * DOCUMENTATION