diff --git a/private/wallpaperrenderthread.cpp b/private/wallpaperrenderthread.cpp
new file mode 100644
index 000000000..9125ebcf3
--- /dev/null
+++ b/private/wallpaperrenderthread.cpp
@@ -0,0 +1,250 @@
+/*
+ Copyright (c) 2007 Paolo Capriotti
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+*/
+
+#include "renderthread.h"
+
+#include
+#include
+#include
+#include
+
+RenderThread::RenderThread()
+: m_current_token(-1)
+, m_size(0, 0)
+{
+ m_abort = false;
+ m_restart = false;
+}
+
+RenderThread::~RenderThread()
+{
+ {
+ // abort computation
+ QMutexLocker lock(&m_mutex);
+ m_abort = true;
+ m_condition.wakeOne();
+ }
+
+ wait();
+}
+
+void RenderThread::setSize(const QSize& size)
+{
+ QMutexLocker lock(&m_mutex);
+ m_size = size;
+}
+
+int RenderThread::render(const QString &file,
+ const QColor &color,
+ Background::ResizeMethod method)
+{
+ int token;
+ {
+ QMutexLocker lock(&m_mutex);
+ m_file = file;
+ m_color = color;
+ m_method = method;
+ m_restart = true;
+ token = ++m_current_token;
+ }
+
+ if (!isRunning()) {
+ start();
+ } else {
+ m_condition.wakeOne();
+ }
+
+ return token;
+}
+
+void RenderThread::run()
+{
+ QString file;
+ QColor color;
+ QSize size;
+ qreal ratio;
+ Background::ResizeMethod method;
+ int token;
+
+ forever {
+ {
+ QMutexLocker lock(&m_mutex);
+
+ while (!m_restart && !m_abort) {
+ m_condition.wait(&m_mutex);
+ }
+
+ if (m_abort) {
+ return;
+ }
+
+ m_restart = false;
+
+ // load all parameters in nonshared variables
+ token = m_current_token;
+ file = m_file;
+ color = m_color;
+ size = m_size;
+ ratio = m_size.width() / qreal(m_size.height());
+ method = m_method;
+ }
+
+ QImage result(size, QImage::Format_ARGB32_Premultiplied);
+ result.fill(color.rgba());
+
+ if (file.isEmpty() || !QFile::exists(file)) {
+ emit done(token, result);
+ continue;
+ }
+
+ QPoint pos(0, 0);
+ bool tiled = false;
+ bool scalable = file.endsWith("svg") || file.endsWith("svgz");
+ QSize scaledSize;
+ QImage img;
+
+ // set image size
+ QSize imgSize;
+ if (scalable) {
+ // scalable: image can be of any size
+ imgSize = size;
+ } else {
+ // otherwise, use the natural size of the loaded image
+ img = QImage(file);
+ imgSize = img.size();
+ kDebug() << "loaded with" << imgSize << ratio;
+ }
+
+ // if any of them is zero we may run into a div-by-zero below.
+ if (imgSize.width() < 1) {
+ imgSize.setWidth(1);
+ }
+
+ if (imgSize.height() < 1) {
+ imgSize.setHeight(1);
+ }
+
+ if (ratio < 1) {
+ ratio = 1;
+ }
+
+ // set render parameters according to resize mode
+ switch (method)
+ {
+ case Background::Scale:
+ imgSize *= ratio;
+ scaledSize = size;
+ break;
+ case Background::Center:
+ scaledSize = imgSize;
+ pos = QPoint((size.width() - scaledSize.width()) / 2,
+ (size.height() - scaledSize.height()) / 2);
+
+ //If the picture is bigger than the screen, shrink it
+ if (size.width() < imgSize.width() && imgSize.width() > imgSize.height()) {
+ int width = size.width();
+ int height = width * scaledSize.height() / imgSize.width();
+ scaledSize = QSize(width, height);
+ pos = QPoint((size.width() - scaledSize.width()) / 2,
+ (size.height() - scaledSize.height()) / 2);
+ } else if (size.height() < imgSize.height()) {
+ int height = size.height();
+ int width = height * imgSize.width() / imgSize.height();
+ scaledSize = QSize(width, height);
+ pos = QPoint((size.width() - scaledSize.width()) / 2,
+ (size.height() - scaledSize.height()) / 2);
+ }
+
+ break;
+ case Background::Maxpect: {
+ imgSize *= ratio;
+ float xratio = (float) size.width() / imgSize.width();
+ float yratio = (float) size.height() / imgSize.height();
+ if (xratio > yratio) {
+ int height = size.height();
+ int width = height * imgSize.width() / imgSize.height();
+ scaledSize = QSize(width, height);
+ } else {
+ int width = size.width();
+ int height = width * imgSize.height() / imgSize.width();
+ scaledSize = QSize(width, height);
+ }
+ pos = QPoint((size.width() - scaledSize.width()) / 2,
+ (size.height() - scaledSize.height()) / 2);
+ break;
+ }
+ case Background::ScaleCrop: {
+ imgSize *= ratio;
+ float xratio = (float) size.width() / imgSize.width();
+ float yratio = (float) size.height() / imgSize.height();
+ if (xratio > yratio) {
+ int width = size.width();
+ int height = width * imgSize.height() / imgSize.width();
+ scaledSize = QSize(width, height);
+ } else {
+ int height = size.height();
+ int width = height * imgSize.width() / imgSize.height();
+ scaledSize = QSize(width, height);
+ }
+ pos = QPoint((size.width() - scaledSize.width()) / 2,
+ (size.height() - scaledSize.height()) / 2);
+ break;
+ }
+ case Background::Tiled:
+ scaledSize = imgSize;
+ tiled = true;
+ break;
+ case Background::CenterTiled:
+ scaledSize = imgSize;
+ pos = QPoint(
+ -scaledSize.width() +
+ ((size.width() - scaledSize.width()) / 2) % scaledSize.width(),
+ -scaledSize.height() +
+ ((size.height() - scaledSize.height()) / 2) % scaledSize.height());
+ tiled = true;
+ break;
+ }
+
+ QPainter p(&result);
+ kDebug() << token << scalable << scaledSize << imgSize;
+ if (scalable) {
+ // tiling is ignored for scalable wallpapers
+ KSvgRenderer svg(file);
+ if (m_restart) {
+ continue;
+ }
+ svg.render(&p);
+ } else {
+ if (scaledSize != imgSize) {
+ img = img.scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ }
+
+ if (m_restart) {
+ continue;
+ }
+
+ if (tiled) {
+ for (int x = pos.x(); x < size.width(); x += scaledSize.width()) {
+ for (int y = pos.y(); y < size.height(); y += scaledSize.height()) {
+ p.drawImage(QPoint(x, y), img);
+ if (m_restart) {
+ goto endLoop;
+ }
+ }
+ }
+ } else {
+ p.drawImage(pos, img);
+ }
+ }
+
+ // signal we're done
+ emit done(token, result);
+ endLoop: continue;
+ }
+}