From 6374635bf388c1912cc7e7baa368b168545c9193 Mon Sep 17 00:00:00 2001 From: "Aaron J. Seigo" Date: Wed, 15 Oct 2008 20:55:07 +0000 Subject: [PATCH] on disk pixmap cache, and use it agressively for svg's. first step towards "no svg parsing on second run"! svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=871870 --- svg.cpp | 132 ++++++++++++++++++++++++++++++------------------------ theme.cpp | 30 ++++++++++++- theme.h | 13 ++++++ 3 files changed, 115 insertions(+), 60 deletions(-) diff --git a/svg.cpp b/svg.cpp index 66c919231..9759cffaa 100644 --- a/svg.cpp +++ b/svg.cpp @@ -22,15 +22,15 @@ #include #include #include -#include #include -#include -#include -#include #include +#include +#include #include #include +#include +#include #include "theme.h" @@ -77,8 +77,21 @@ class SvgPrivate eraseRenderer(); } - void setImagePath(const QString &imagePath, Svg *q) + bool setImagePath(const QString &imagePath, Svg *q) { + bool isThemed = !QDir::isAbsolutePath(imagePath); + + // lets check to see if we're already set to this file + if (isThemed == themed && + ((themed && themePath == imagePath) || + (!themed && path == imagePath))) { + return false; + } + + // if we don't have any path right now and are going to set one, + // then lets not schedule a repaint because we are just initializing! + bool updateNeeded = true; //!path.isEmpty() || !themePath.isEmpty(); + if (themed) { QObject::disconnect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), q, SLOT(themeChanged())); @@ -86,7 +99,7 @@ class SvgPrivate q, SLOT(colorsChanged())); } - themed = !QDir::isAbsolutePath(imagePath); + themed = isThemed; path.clear(); themePath.clear(); @@ -96,38 +109,22 @@ class SvgPrivate q, SLOT(themeChanged())); // check if svg wants colorscheme applied - createRenderer(); - applyColors = renderer->elementExists("hint-apply-color-scheme"); + checkApplyColorHint(); if (applyColors && !Theme::defaultTheme()->colorScheme()) { QObject::connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), q, SLOT(colorsChanged())); } - - } else { + } else if (QFile::exists(imagePath)) { path = imagePath; - - if (!QFile::exists(path)) { - kDebug() << "file '" << path << "' does not exist!"; - } - } - } - - void removeFromCache() { - if (ids.isEmpty()) { - return; + } else { + kDebug() << "file '" << path << "' does not exist!"; } - foreach (const QString &id, ids) { - QPixmapCache::remove(id); - } - - ids.clear(); + return updateNeeded; } QPixmap findInCache(const QString &elementId, const QSizeF &s = QSizeF()) { - createRenderer(); - QSize size; if (elementId.isEmpty() || multipleImages) { size = s.toSize(); @@ -145,16 +142,14 @@ class SvgPrivate if (!elementId.isEmpty()) { id.append(elementId); } + //kDebug() << "id is " << id; - if (!ids.contains(id)) { - ids.append(id); - } - + Theme *theme = Theme::defaultTheme(); QPixmap p; - if (QPixmapCache::find(id, p)) { - //kDebug() << "found cached version of " << id; + if (theme->findInCache(id, p)) { + //kDebug() << "found cached version of " << id << p.size(); return p; } else { //kDebug() << "didn't find cached version of " << id << ", so re-rendering"; @@ -168,6 +163,7 @@ class SvgPrivate p.fill(Qt::transparent); QPainter renderPainter(&p); + createRenderer(); if (elementId.isEmpty()) { renderer->render(&renderPainter); } else { @@ -179,15 +175,11 @@ class SvgPrivate // Apply current color scheme if the svg asks for it if (applyColors) { QImage itmp = p.toImage(); - KIconEffect::colorize( - itmp, Theme::defaultTheme()->color(Theme::BackgroundColor), 1.0); + KIconEffect::colorize(itmp, theme->color(Theme::BackgroundColor), 1.0); p = p.fromImage(itmp); } - if (!QPixmapCache::insert(id, p)) { - //kDebug() << "pixmap cache is too small for inserting" << id << "of size" << s; - } - + theme->insertIntoCache(id, p); return p; } @@ -201,14 +193,14 @@ class SvgPrivate path = Plasma::Theme::defaultTheme()->imagePath(themePath); } - QHash::const_iterator it = renderers.find(path); + QHash::const_iterator it = s_renderers.find(path); - if (it != renderers.end()) { + if (it != s_renderers.end()) { //kDebug() << "gots us an existing one!"; renderer = it.value(); } else { renderer = new SharedSvgRenderer(path); - renderers[path] = renderer; + s_renderers[path] = renderer; } size = renderer->defaultSize(); @@ -218,7 +210,7 @@ class SvgPrivate { if (renderer && renderer.count() == 2) { // this and the cache reference it; and boy is this not thread safe ;) - renderers.erase(renderers.find(path)); + s_renderers.erase(s_renderers.find(path)); } renderer = 0; @@ -260,6 +252,19 @@ class SvgPrivate return renderer->matrixForElement(elementId); } + void checkApplyColorHint() + { + KConfigGroup cg(KGlobal::config(), "SvgHints"); + QString cgKey = themePath + "-hint-apply-color-scheme"; + if (cg.hasKey(cgKey)) { + applyColors = cg.readEntry(cgKey, false); + } else { + createRenderer(); + applyColors = renderer->elementExists("hint-apply-color-scheme"); + cg.writeEntry(cgKey, applyColors); + } + } + void themeChanged() { if (!themed) { @@ -272,22 +277,24 @@ class SvgPrivate return; } - removeFromCache(); path = newPath; //delete d->renderer; we're a KSharedPtr eraseRenderer(); // check if new theme svg wants colorscheme applied - createRenderer(); - applyColors = renderer->elementExists("hint-apply-color-scheme"); + bool wasApplyColors = applyColors; + checkApplyColorHint(); if (applyColors && !Theme::defaultTheme()->colorScheme()) { - QObject::connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), - q, SLOT(colorsChanged())); + if (!wasApplyColors) { + QObject::connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), + q, SLOT(colorsChanged())); + } } else { QObject::disconnect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), q, SLOT(colorsChanged())); } + //kDebug() << themePath << ">>>>>>>>>>>>>>>>>> theme changed"; emit q->repaintNeeded(); } @@ -297,24 +304,22 @@ class SvgPrivate return; } - removeFromCache(); eraseRenderer(); emit q->repaintNeeded(); } Svg *q; - static QHash renderers; + static QHash s_renderers; SharedSvgRenderer::Ptr renderer; QString themePath; QString path; - QList ids; QSizeF size; bool multipleImages; bool themed; bool applyColors; }; -QHash SvgPrivate::renderers; +QHash SvgPrivate::s_renderers; Svg::Svg(QObject *parent) : QObject(parent), @@ -371,14 +376,16 @@ void Svg::resize(qreal width, qreal height) void Svg::resize(const QSizeF &size) { - d->createRenderer(); d->size = size; } void Svg::resize() { - d->createRenderer(); - d->size = d->renderer->defaultSize(); + if (d->renderer) { + d->size = d->renderer->defaultSize(); + } else { + d->size = QSizeF(); + } } QSize Svg::elementSize(const QString &elementId) const @@ -393,6 +400,10 @@ QRectF Svg::elementRect(const QString &elementId) const bool Svg::hasElement(const QString &elementId) const { + if (d->path.isNull() && d->themePath.isNull()) { + return false; + } + d->createRenderer(); return d->renderer->elementExists(elementId); } @@ -415,6 +426,10 @@ FIXME: implement when Qt can support us! bool Svg::isValid() const { + if (d->path.isNull() && d->themePath.isNull()) { + return false; + } + d->createRenderer(); return d->renderer->isValid(); } @@ -431,9 +446,10 @@ bool Svg::containsMultipleImages() const void Svg::setImagePath(const QString &svgFilePath) { - d->setImagePath(svgFilePath, this); - d->eraseRenderer(); - emit repaintNeeded(); + if (d->setImagePath(svgFilePath, this)) { + } + d->eraseRenderer(); + emit repaintNeeded(); } QString Svg::imagePath() const diff --git a/theme.cpp b/theme.cpp index 99edd642a..1a9556ed7 100644 --- a/theme.cpp +++ b/theme.cpp @@ -25,15 +25,17 @@ #include #endif -#include #include +#include #include #include #include +#include +#include #include #include #include -#include +#include #include "private/packages_p.h" @@ -56,6 +58,7 @@ public: defaultWallpaperSuffix(DEFAULT_WALLPAPER_SUFFIX), defaultWallpaperWidth(DEFAULT_WALLPAPER_WIDTH), defaultWallpaperHeight(DEFAULT_WALLPAPER_HEIGHT), + pixmapCache(KGlobal::mainComponent().componentName()), locolor(false), compositingActive(KWindowSystem::compositingActive()), isDefault(false), @@ -65,6 +68,10 @@ public: generalFont = QApplication::font(); } + ~ThemePrivate() + { + } + KConfigGroup &config() { if (!cfg.isValid()) { @@ -102,6 +109,7 @@ public: QString defaultWallpaperSuffix; int defaultWallpaperWidth; int defaultWallpaperHeight; + KPixmapCache pixmapCache; #ifdef Q_WS_X11 KSelectionWatcher *compositeWatch; @@ -232,6 +240,14 @@ void Theme::setThemeName(const QString &themeName) theme = ThemePrivate::defaultTheme; } + if (d->themeName == theme) { + return; + } + + if (!d->themeName.isEmpty()) { + d->pixmapCache.discard(); + } + d->themeName = theme; // load the color scheme config @@ -466,6 +482,16 @@ bool Theme::useGlobalSettings() const return d->useGlobal; } +bool Theme::findInCache(const QString &key, QPixmap &pix) +{ + return d->pixmapCache.find(key, pix); +} + +void Theme::insertIntoCache(const QString& key, const QPixmap& pix) +{ + d->pixmapCache.insert(key, pix); +} + } #include diff --git a/theme.h b/theme.h index 6c4d9b6a3..f61d6e784 100644 --- a/theme.h +++ b/theme.h @@ -179,6 +179,19 @@ class PLASMA_EXPORT Theme : public QObject */ bool useGlobalSettings() const; + /** + * Tries to load pixmap with the specified key from cache. + * @return true when pixmap was found and loaded from cache, false otherwise + **/ + bool findInCache(const QString &key, QPixmap &pix); + + /** + * Insert specified pixmap into the cache. + * If the cache already contains pixmap with the specified key then it is + * overwritten. + **/ + void insertIntoCache(const QString& key, const QPixmap& pix); + Q_SIGNALS: /** * Emitted when the user changes the theme. SVGs should be reloaded at