Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / plasma / containments / desktop / renderthread.cpp
blob1d999dd48d23c01a0a6f3efff9bc5c641fbcc77e
1 /*
2 Copyright (c) 2007 Paolo Capriotti <p.capriotti@gmail.com>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 */
10 #include "renderthread.h"
12 #include <QPainter>
13 #include <QFile>
14 #include <KDebug>
15 #include <KSvgRenderer>
17 RenderThread::RenderThread(const QSize &size, float ratio)
18 : m_current_token(-1)
19 , m_size(size)
20 , m_ratio(ratio)
22 m_abort = false;
23 m_restart = false;
26 RenderThread::~RenderThread()
29 // abort computation
30 QMutexLocker lock(&m_mutex);
31 m_abort = true;
32 m_condition.wakeOne();
35 wait();
38 void RenderThread::setSize(const QSize& size)
40 QMutexLocker lock(&m_mutex);
41 m_size = size;
44 int RenderThread::render(const QString &file,
45 const QColor &color,
46 Background::ResizeMethod method,
47 Qt::TransformationMode mode)
49 int token;
51 QMutexLocker lock(&m_mutex);
52 m_file = file;
53 m_color = color;
54 m_method = method;
55 m_mode = mode;
56 m_restart = true;
57 token = ++m_current_token;
60 if (!isRunning()) {
61 start();
63 else {
64 m_condition.wakeOne();
67 return token;
70 void RenderThread::run()
72 QString file;
73 QColor color;
74 QSize size;
75 float ratio;
76 Background::ResizeMethod method;
77 Qt::TransformationMode mode;
78 int token;
80 forever {
82 QMutexLocker lock(&m_mutex);
83 while (!m_restart && !m_abort) {
84 m_condition.wait(&m_mutex);
86 if (m_abort) {
87 return;
89 m_restart = false;
91 // load all parameters in nonshared variables
92 token = m_current_token;
93 file = m_file;
94 color = m_color;
95 size = m_size;
96 ratio = m_ratio;
97 method = m_method;
98 mode = m_mode;
101 QImage result(size, QImage::Format_ARGB32_Premultiplied);
102 result.fill(color.rgb());
104 if (file.isEmpty() || !QFile::exists(file)) {
105 emit done(token, result);
106 continue;
109 QPoint pos(0, 0);
110 bool tiled = false;
111 bool scalable = file.endsWith("svg") || file.endsWith("svgz");
112 QSize scaledSize;
113 QImage img;
115 // load nonscalable image
116 if (!scalable) {
117 img = QImage(file);
120 // set image size
121 QSize imgSize;
122 if (scalable) {
123 // scalable: image can be of any size
124 imgSize = size;
126 else {
127 // otherwise, use the natural size of the loaded image
128 imgSize = img.size();
130 imgSize *= ratio;
132 // if any of them is zero we may run into a div-by-zero below.
133 if (imgSize.width() == 0) {
134 imgSize.setWidth(1);
136 if (imgSize.height() == 0) {
137 imgSize.setHeight(1);
140 // set render parameters according to resize mode
141 switch (method)
143 case Background::Scale:
144 scaledSize = size;
145 break;
146 case Background::Center:
147 scaledSize = imgSize;
148 pos = QPoint((size.width() - scaledSize.width()) / 2,
149 (size.height() - scaledSize.height()) / 2);
150 break;
151 case Background::ScaleCrop: {
152 float xratio = (float) size.width() / imgSize.width();
153 float yratio = (float) size.height() / imgSize.height();
154 if (xratio > yratio) {
155 int width = size.width();
156 int height = width * imgSize.height() / imgSize.width();
157 scaledSize = QSize(width, height);
159 else {
160 int height = size.height();
161 int width = height * imgSize.width() / imgSize.height();
162 scaledSize = QSize(width, height);
164 pos = QPoint((size.width() - scaledSize.width()) / 2,
165 (size.height() - scaledSize.height()) / 2);
166 break;
168 case Background::Tiled:
169 scaledSize = imgSize;
170 tiled = true;
171 break;
172 case Background::CenterTiled:
173 scaledSize = imgSize;
174 pos = QPoint(
175 -scaledSize.width() +
176 ((size.width() - scaledSize.width()) / 2) % scaledSize.width(),
177 -scaledSize.height() +
178 ((size.height() - scaledSize.height()) / 2) % scaledSize.height());
179 tiled = true;
180 break;
183 QPainter p(&result);
184 if (scalable) {
185 // tiling is ignored for scalable wallpapers
186 KSvgRenderer svg(file);
187 if (m_restart) {
188 continue;
190 svg.render(&p);
192 else {
193 QImage scaled = img.scaled(scaledSize, Qt::IgnoreAspectRatio, mode);
194 if (m_restart) {
195 continue;
197 if (tiled) {
198 for (int x = pos.x(); x < size.width(); x += scaledSize.width()) {
199 for (int y = pos.y(); y < size.height(); y += scaledSize.height()) {
200 p.drawImage(QPoint(x, y), scaled);
201 if (m_restart) {
202 goto endLoop;
207 else {
208 p.drawImage(pos, scaled);
212 // signal we're done
213 emit done(token, result);
215 endLoop: continue;