Plasma
wallpaperrenderthread.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "plasma/private/wallpaperrenderthread_p.h"
00022
00023 #include <QPainter>
00024 #include <QFile>
00025 #include <QSvgRenderer>
00026
00027 #include <kdebug.h>
00028
00029 namespace Plasma
00030 {
00031
00032 WallpaperRenderThread::WallpaperRenderThread(QObject *parent)
00033 : QThread(parent),
00034 m_lastToken(-1)
00035 {
00036 m_abort = false;
00037 }
00038
00039 WallpaperRenderThread::~WallpaperRenderThread()
00040 {
00041 {
00042
00043 QMutexLocker lock(&m_mutex);
00044 m_abort = true;
00045 }
00046
00047 wait();
00048 }
00049
00050 int WallpaperRenderThread::render(const QString &file,
00051 const QSize &size,
00052 Wallpaper::ResizeMethod method,
00053 const QColor &color)
00054 {
00055 int token;
00056 RenderTask task;
00057 task.file = file;
00058 task.color = color;
00059 task.resizeMethod = method;
00060 task.size = size;
00061 {
00062 QMutexLocker lock(&m_mutex);
00063 task.token = ++m_lastToken;
00064 m_tasks.enqueue(task);
00065 }
00066
00067 if (!isRunning()) {
00068 start();
00069 }
00070
00071 return token;
00072 }
00073
00074 void WallpaperRenderThread::run()
00075 {
00076 qreal ratio;
00077 RenderTask task;
00078
00079 forever {
00080 {
00081 QMutexLocker lock(&m_mutex);
00082
00083 if (m_tasks.isEmpty() || m_abort) {
00084 return;
00085 }
00086
00087
00088 task = m_tasks.dequeue();
00089 ratio = task.size.width() / qreal(task.size.height());
00090 }
00091
00092 QImage result(task.size, QImage::Format_ARGB32_Premultiplied);
00093 result.fill(task.color.rgba());
00094
00095 if (task.file.isEmpty() || !QFile::exists(task.file)) {
00096 emit done(task.token, result, task.file, task.size, task.resizeMethod, task.color);
00097 break;
00098 }
00099
00100 QPoint pos(0, 0);
00101 bool tiled = false;
00102 bool scalable = task.file.endsWith("svg") || task.file.endsWith("svgz");
00103 QSize scaledSize;
00104 QImage img;
00105
00106
00107 QSize imgSize;
00108 if (scalable) {
00109
00110 imgSize = task.size;
00111 } else {
00112
00113 img = QImage(task.file);
00114 imgSize = img.size();
00115
00116 }
00117
00118
00119 if (imgSize.width() < 1) {
00120 imgSize.setWidth(1);
00121 }
00122
00123 if (imgSize.height() < 1) {
00124 imgSize.setHeight(1);
00125 }
00126
00127 if (ratio < 1) {
00128 ratio = 1;
00129 }
00130
00131
00132 switch (task.resizeMethod)
00133 {
00134 case Wallpaper::ScaledResize:
00135 imgSize *= ratio;
00136 scaledSize = task.size;
00137 break;
00138 case Wallpaper::CenteredResize:
00139 scaledSize = imgSize;
00140 pos = QPoint((task.size.width() - scaledSize.width()) / 2,
00141 (task.size.height() - scaledSize.height()) / 2);
00142
00143
00144 if (task.size.width() < imgSize.width() && imgSize.width() > imgSize.height()) {
00145 int width = task.size.width();
00146 int height = width * scaledSize.height() / imgSize.width();
00147 scaledSize = QSize(width, height);
00148 pos = QPoint((task.size.width() - scaledSize.width()) / 2,
00149 (task.size.height() - scaledSize.height()) / 2);
00150 } else if (task.size.height() < imgSize.height()) {
00151 int height = task.size.height();
00152 int width = height * imgSize.width() / imgSize.height();
00153 scaledSize = QSize(width, height);
00154 pos = QPoint((task.size.width() - scaledSize.width()) / 2,
00155 (task.size.height() - scaledSize.height()) / 2);
00156 }
00157
00158 break;
00159 case Wallpaper::MaxpectResize: {
00160 imgSize *= ratio;
00161 float xratio = (float) task.size.width() / imgSize.width();
00162 float yratio = (float) task.size.height() / imgSize.height();
00163 if (xratio > yratio) {
00164 int height = task.size.height();
00165 int width = height * imgSize.width() / imgSize.height();
00166 scaledSize = QSize(width, height);
00167 } else {
00168 int width = task.size.width();
00169 int height = width * imgSize.height() / imgSize.width();
00170 scaledSize = QSize(width, height);
00171 }
00172 pos = QPoint((task.size.width() - scaledSize.width()) / 2,
00173 (task.size.height() - scaledSize.height()) / 2);
00174 break;
00175 }
00176 case Wallpaper::ScaledAndCroppedResize: {
00177 imgSize *= ratio;
00178 float xratio = (float) task.size.width() / imgSize.width();
00179 float yratio = (float) task.size.height() / imgSize.height();
00180 if (xratio > yratio) {
00181 int width = task.size.width();
00182 int height = width * imgSize.height() / imgSize.width();
00183 scaledSize = QSize(width, height);
00184 } else {
00185 int height = task.size.height();
00186 int width = height * imgSize.width() / imgSize.height();
00187 scaledSize = QSize(width, height);
00188 }
00189 pos = QPoint((task.size.width() - scaledSize.width()) / 2,
00190 (task.size.height() - scaledSize.height()) / 2);
00191 break;
00192 }
00193 case Wallpaper::TiledResize:
00194 scaledSize = imgSize;
00195 tiled = true;
00196 break;
00197 case Wallpaper::CenterTiledResize:
00198 scaledSize = imgSize;
00199 pos = QPoint(
00200 -scaledSize.width() +
00201 ((task.size.width() - scaledSize.width()) / 2) % scaledSize.width(),
00202 -scaledSize.height() +
00203 ((task.size.height() - scaledSize.height()) / 2) % scaledSize.height());
00204 tiled = true;
00205 break;
00206 }
00207
00208 QPainter p(&result);
00209
00210 if (scalable) {
00211
00212 QSvgRenderer svg(task.file);
00213 if (m_abort) {
00214 return;
00215 }
00216 svg.render(&p);
00217 } else {
00218 if (scaledSize != imgSize) {
00219 img = img.scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
00220 }
00221
00222 if (m_abort) {
00223 return;
00224 }
00225
00226 if (tiled) {
00227 for (int x = pos.x(); x < task.size.width(); x += scaledSize.width()) {
00228 for (int y = pos.y(); y < task.size.height(); y += scaledSize.height()) {
00229 p.drawImage(QPoint(x, y), img);
00230 if (m_abort) {
00231 return;
00232 }
00233 }
00234 }
00235 } else {
00236 p.drawImage(pos, img);
00237 }
00238 }
00239
00240
00241 emit done(task.token, result, task.file, task.size, task.resizeMethod, task.color);
00242 }
00243 }
00244
00245 }
00246
00247 #include "wallpaperrenderthread_p.moc"
00248