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