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(const QSize &size, float ratio)
00018 : m_current_token(-1)
00019 , m_size(size)
00020 , m_ratio(ratio)
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 int RenderThread::render(const QString &file,
00045 const QColor &color,
00046 Background::ResizeMethod method,
00047 Qt::TransformationMode mode)
00048 {
00049 int token;
00050 {
00051 QMutexLocker lock(&m_mutex);
00052 m_file = file;
00053 m_color = color;
00054 m_method = method;
00055 m_mode = mode;
00056 m_restart = true;
00057 token = ++m_current_token;
00058 }
00059
00060 if (!isRunning()) {
00061 start();
00062 }
00063 else {
00064 m_condition.wakeOne();
00065 }
00066
00067 return token;
00068 }
00069
00070 void RenderThread::run()
00071 {
00072 QString file;
00073 QColor color;
00074 QSize size;
00075 float ratio;
00076 Background::ResizeMethod method;
00077 Qt::TransformationMode mode;
00078 int token;
00079
00080 forever {
00081 {
00082 QMutexLocker lock(&m_mutex);
00083 while (!m_restart && !m_abort) {
00084 m_condition.wait(&m_mutex);
00085 }
00086 if (m_abort) {
00087 return;
00088 }
00089 m_restart = false;
00090
00091
00092 token = m_current_token;
00093 file = m_file;
00094 color = m_color;
00095 size = m_size;
00096 ratio = m_ratio;
00097 method = m_method;
00098 mode = m_mode;
00099 }
00100
00101 QImage result(size, QImage::Format_ARGB32_Premultiplied);
00102 result.fill(color.rgba());
00103
00104 if (file.isEmpty() || !QFile::exists(file)) {
00105 emit done(token, result);
00106 continue;
00107 }
00108
00109 QPoint pos(0, 0);
00110 bool tiled = false;
00111 bool scalable = file.endsWith("svg") || file.endsWith("svgz");
00112 QSize scaledSize;
00113 QImage img;
00114
00115
00116 if (!scalable) {
00117 img = QImage(file);
00118 }
00119
00120
00121 QSize imgSize;
00122 if (scalable) {
00123
00124 imgSize = size;
00125 }
00126 else {
00127
00128 imgSize = img.size();
00129 }
00130 imgSize *= ratio;
00131
00132
00133 if (imgSize.width() == 0) {
00134 imgSize.setWidth(1);
00135 }
00136 if (imgSize.height() == 0) {
00137 imgSize.setHeight(1);
00138 }
00139
00140
00141 switch (method)
00142 {
00143 case Background::Scale:
00144 scaledSize = size;
00145 break;
00146 case Background::Center:
00147 scaledSize = imgSize;
00148 pos = QPoint((size.width() - scaledSize.width()) / 2,
00149 (size.height() - scaledSize.height()) / 2);
00150
00151
00152 if( size.width() < imgSize.width() && imgSize.width() > imgSize.height() )
00153 {
00154 int width = size.width();
00155 int height = width * scaledSize.height() / imgSize.width();
00156 scaledSize = QSize(width, height);
00157 pos = QPoint((size.width() - scaledSize.width()) / 2,
00158 (size.height() - scaledSize.height()) / 2);
00159 }
00160 else if( size.height() < imgSize.height() )
00161 {
00162 int height = size.height();
00163 int width = height * imgSize.width() / imgSize.height();
00164 scaledSize = QSize(width, height);
00165 pos = QPoint((size.width() - scaledSize.width()) / 2,
00166 (size.height() - scaledSize.height()) / 2);
00167 }
00168
00169 break;
00170 case Background::ScaleCrop: {
00171 float xratio = (float) size.width() / imgSize.width();
00172 float yratio = (float) size.height() / imgSize.height();
00173 if (xratio > yratio) {
00174 int width = size.width();
00175 int height = width * imgSize.height() / imgSize.width();
00176 scaledSize = QSize(width, height);
00177 }
00178 else {
00179 int height = size.height();
00180 int width = height * imgSize.width() / imgSize.height();
00181 scaledSize = QSize(width, height);
00182 }
00183 pos = QPoint((size.width() - scaledSize.width()) / 2,
00184 (size.height() - scaledSize.height()) / 2);
00185 break;
00186 }
00187 case Background::Tiled:
00188 scaledSize = imgSize;
00189 tiled = true;
00190 break;
00191 case Background::CenterTiled:
00192 scaledSize = imgSize;
00193 pos = QPoint(
00194 -scaledSize.width() +
00195 ((size.width() - scaledSize.width()) / 2) % scaledSize.width(),
00196 -scaledSize.height() +
00197 ((size.height() - scaledSize.height()) / 2) % scaledSize.height());
00198 tiled = true;
00199 break;
00200 }
00201
00202 QPainter p(&result);
00203 if (scalable) {
00204
00205 KSvgRenderer svg(file);
00206 if (m_restart) {
00207 continue;
00208 }
00209 svg.render(&p);
00210 }
00211 else {
00212 QImage scaled = img.scaled(scaledSize, Qt::IgnoreAspectRatio, mode);
00213 if (m_restart) {
00214 continue;
00215 }
00216 if (tiled) {
00217 for (int x = pos.x(); x < size.width(); x += scaledSize.width()) {
00218 for (int y = pos.y(); y < size.height(); y += scaledSize.height()) {
00219 p.drawImage(QPoint(x, y), scaled);
00220 if (m_restart) {
00221 goto endLoop;
00222 }
00223 }
00224 }
00225 }
00226 else {
00227 p.drawImage(pos, scaled);
00228 }
00229 }
00230
00231
00232 emit done(token, result);
00233
00234 endLoop: continue;
00235 }
00236 }