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
This commit is contained in:
Aaron J. Seigo 2008-10-15 20:55:07 +00:00
parent 047c0dde89
commit 6374635bf3
3 changed files with 115 additions and 60 deletions

120
svg.cpp
View File

@ -22,15 +22,15 @@
#include <QDir>
#include <QMatrix>
#include <QPainter>
#include <QPixmapCache>
#include <QSharedData>
#include <KDebug>
#include <KSharedPtr>
#include <KSvgRenderer>
#include <KColorScheme>
#include <KConfigGroup>
#include <KDebug>
#include <KIconEffect>
#include <KGlobalSettings>
#include <KSharedPtr>
#include <KSvgRenderer>
#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)) {
} else {
kDebug() << "file '" << path << "' does not exist!";
}
}
}
void removeFromCache() {
if (ids.isEmpty()) {
return;
}
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<QString, SharedSvgRenderer::Ptr>::const_iterator it = renderers.find(path);
QHash<QString, SharedSvgRenderer::Ptr>::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()) {
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<QString, SharedSvgRenderer::Ptr> renderers;
static QHash<QString, SharedSvgRenderer::Ptr> s_renderers;
SharedSvgRenderer::Ptr renderer;
QString themePath;
QString path;
QList<QString> ids;
QSizeF size;
bool multipleImages;
bool themed;
bool applyColors;
};
QHash<QString, SharedSvgRenderer::Ptr> SvgPrivate::renderers;
QHash<QString, SharedSvgRenderer::Ptr> 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();
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,7 +446,8 @@ bool Svg::containsMultipleImages() const
void Svg::setImagePath(const QString &svgFilePath)
{
d->setImagePath(svgFilePath, this);
if (d->setImagePath(svgFilePath, this)) {
}
d->eraseRenderer();
emit repaintNeeded();
}

View File

@ -25,15 +25,17 @@
#include <QX11Info>
#endif
#include <KWindowSystem>
#include <KColorScheme>
#include <KComponentData>
#include <KConfigGroup>
#include <KDebug>
#include <KGlobal>
#include <KGlobalSettings>
#include <KPixmapCache>
#include <KSelectionWatcher>
#include <KSharedConfig>
#include <KStandardDirs>
#include <KGlobalSettings>
#include <KWindowSystem>
#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 <theme.moc>

13
theme.h
View File

@ -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