Commit 458eb50b3163bca241916e93bd6a21dc598d6b6f

  • Tree SHA1: 6749ea4
  • Parent SHA1: ae5205f (Work on being able to wait on a Thinker who has been queued but not started, and thus manager thread must be ready to push it to the thinker thread either via slot or during a call into the library)
  • raw diff | raw patch
Mandelbrot sample changes to use Thinker-Qt.  (Submitted in a single diff for easy review on gitorious)
  
44** All rights reserved.
55** Contact: Nokia Corporation (qt-info@nokia.com)
66**
7** This file is part of the examples of the Qt Toolkit.
7** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/
88**
99** $QT_BEGIN_LICENSE:LGPL$
1010** No Commercial Usage
  
44** All rights reserved.
55** Contact: Nokia Corporation (qt-info@nokia.com)
66**
7** This file is part of the examples of the Qt Toolkit.
7** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/
88**
99** $QT_BEGIN_LICENSE:LGPL$
1010** No Commercial Usage
5454 pixmapScale = DefaultScale;
5555 curScale = DefaultScale;
5656
57 qRegisterMetaType<QImage>("QImage");
58 connect(&thread, SIGNAL(renderedImage(const QImage &, double)),
59 this, SLOT(updatePixmap(const QImage &, double)));
57 for (int i = 0; i < ColormapSize; ++i)
58 colormap[i] = rgbFromWaveLength(380.0 + (i * 400.0 / ColormapSize));
6059
60 connect(&watcher, SIGNAL(written()), this, SLOT(updatePixmap()));
61 watcher.setThrottleTime(400);
62
6163 setWindowTitle(tr("Mandelbrot"));
6264#ifndef QT_NO_CURSOR
6365 setCursor(Qt::CrossCursor);
6767 resize(550, 400);
6868}
6969
70MandelbrotWidget::~MandelbrotWidget()
71{
72 watcher.cancel();
73}
74
75void MandelbrotWidget::resetThinker(double centerX, double centerY,
76 double scaleFactor, QSize resultSize)
77{
78 watcher.cancel();
79
80 RenderThinker* thinker = new RenderThinker(centerX, centerY,
81 scaleFactor, resultSize, colormap);
82 watcher.setPresent(ThinkerQt::run(thinker));
83}
84
7085void MandelbrotWidget::paintEvent(QPaintEvent * /* event */)
7186{
7287 QPainter painter(this);
127127
128128void MandelbrotWidget::resizeEvent(QResizeEvent * /* event */)
129129{
130 thread.render(centerX, centerY, curScale, size());
130 resetThinker(centerX, centerY, curScale, size());
131131}
132132
133133void MandelbrotWidget::keyPressEvent(QKeyEvent *event)
190190 }
191191}
192192
193void MandelbrotWidget::updatePixmap(const QImage &image, double scaleFactor)
193void MandelbrotWidget::updatePixmap()
194194{
195195 if (!lastDragPos.isNull())
196196 return;
197197
198 pixmap = QPixmap::fromImage(image);
199 pixmapOffset = QPoint();
200 lastDragPos = QPoint();
201 pixmapScale = scaleFactor;
202 update();
198 RenderThinker::SnapshotPointer snap = watcher.createSnapshot();
199 if (snap->hasImage()) {
200 pixmap = QPixmap::fromImage(snap->getImage());
201 pixmapScale = snap->getScaleFactor();
202 snap.clear();
203 pixmapOffset = QPoint();
204 lastDragPos = QPoint();
205 update();
206 }
203207}
204208
205209void MandelbrotWidget::zoom(double zoomFactor)
206210{
207211 curScale *= zoomFactor;
208212 update();
209 thread.render(centerX, centerY, curScale, size());
213 resetThinker(centerX, centerY, curScale, size());
210214}
211215
212216void MandelbrotWidget::scroll(int deltaX, int deltaY)
218218 centerX += deltaX * curScale;
219219 centerY += deltaY * curScale;
220220 update();
221 thread.render(centerX, centerY, curScale, size());
221 resetThinker(centerX, centerY, curScale, size());
222}
223
224uint MandelbrotWidget::rgbFromWaveLength(double wave)
225{
226 double r = 0.0;
227 double g = 0.0;
228 double b = 0.0;
229
230 if (wave >= 380.0 && wave <= 440.0) {
231 r = -1.0 * (wave - 440.0) / (440.0 - 380.0);
232 b = 1.0;
233 } else if (wave >= 440.0 && wave <= 490.0) {
234 g = (wave - 440.0) / (490.0 - 440.0);
235 b = 1.0;
236 } else if (wave >= 490.0 && wave <= 510.0) {
237 g = 1.0;
238 b = -1.0 * (wave - 510.0) / (510.0 - 490.0);
239 } else if (wave >= 510.0 && wave <= 580.0) {
240 r = (wave - 510.0) / (580.0 - 510.0);
241 g = 1.0;
242 } else if (wave >= 580.0 && wave <= 645.0) {
243 r = 1.0;
244 g = -1.0 * (wave - 645.0) / (645.0 - 580.0);
245 } else if (wave >= 645.0 && wave <= 780.0) {
246 r = 1.0;
247 }
248
249 double s = 1.0;
250 if (wave > 700.0)
251 s = 0.3 + 0.7 * (780.0 - wave) / (780.0 - 700.0);
252 else if (wave < 420.0)
253 s = 0.3 + 0.7 * (wave - 380.0) / (420.0 - 380.0);
254
255 r = pow(r * s, 0.8);
256 g = pow(g * s, 0.8);
257 b = pow(b * s, 0.8);
258 return qRgb(int(r * 255), int(g * 255), int(b * 255));
222259}
  
44** All rights reserved.
55** Contact: Nokia Corporation (qt-info@nokia.com)
66**
7** This file is part of the examples of the Qt Toolkit.
7** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/
88**
99** $QT_BEGIN_LICENSE:LGPL$
1010** No Commercial Usage
3737
3838#include <QPixmap>
3939#include <QWidget>
40#include "thinkerqt/thinkerqt.h"
4041
4142#include "renderthread.h"
4243
4747
4848public:
4949 MandelbrotWidget(QWidget *parent = 0);
50 ~MandelbrotWidget();
5051
5152protected:
5253 void paintEvent(QPaintEvent *event);
5959 void mouseReleaseEvent(QMouseEvent *event);
6060
6161private slots:
62 void updatePixmap(const QImage &image, double scaleFactor);
62 void updatePixmap(); /* makes snapshot to get image & scaleFactor */
6363
6464private:
6565 void zoom(double zoomFactor);
6666 void scroll(int deltaX, int deltaY);
67 uint rgbFromWaveLength(double wave);
6768
68 RenderThread thread;
69 RenderThinker::PresentWatcher watcher;
70 void resetThinker(double centerX, double centerY, double scaleFactor,
71 QSize resultSize);
72
6973 QPixmap pixmap;
7074 QPoint pixmapOffset;
7175 QPoint lastDragPos;
7777 double centerY;
7878 double pixmapScale;
7979 double curScale;
80 Colormap colormap;
8081};
8182
8283#endif
  
44** All rights reserved.
55** Contact: Nokia Corporation (qt-info@nokia.com)
66**
7** This file is part of the examples of the Qt Toolkit.
7** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/
88**
99** $QT_BEGIN_LICENSE:LGPL$
1010** No Commercial Usage
3838
3939#include "renderthread.h"
4040
41RenderThread::RenderThread(QObject *parent)
42 : QThread(parent)
41RenderThinker::RenderThinker(double centerX, double centerY, double scaleFactor,
42 QSize resultSize, const Colormap& colormap)
43 : centerX (centerX),
44 centerY (centerY),
45 scaleFactor (scaleFactor),
46 resultSize (resultSize),
47 colormap (colormap)
4348{
44 restart = false;
45 abort = false;
46
47 for (int i = 0; i < ColormapSize; ++i)
48 colormap[i] = rgbFromWaveLength(380.0 + (i * 400.0 / ColormapSize));
4949}
5050
51RenderThread::~RenderThread()
51void RenderThinker::start()
5252{
53 mutex.lock();
54 abort = true;
55 condition.wakeOne();
56 mutex.unlock();
57
58 wait();
59}
60
61void RenderThread::render(double centerX, double centerY, double scaleFactor,
62 QSize resultSize)
63{
64 QMutexLocker locker(&mutex);
65
66 this->centerX = centerX;
67 this->centerY = centerY;
68 this->scaleFactor = scaleFactor;
69 this->resultSize = resultSize;
70
71 if (!isRunning()) {
72 start(LowPriority);
73 } else {
74 restart = true;
75 condition.wakeOne();
76 }
77}
78
79void RenderThread::run()
80{
81 forever {
82 mutex.lock();
83 QSize resultSize = this->resultSize;
84 double scaleFactor = this->scaleFactor;
85 double centerX = this->centerX;
86 double centerY = this->centerY;
87 mutex.unlock();
88
8953 int halfWidth = resultSize.width() / 2;
9054 int halfHeight = resultSize.height() / 2;
9155 QImage image(resultSize, QImage::Format_RGB32);
6262 bool allBlack = true;
6363
6464 for (int y = -halfHeight; y < halfHeight; ++y) {
65 if (restart)
66 break;
67 if (abort)
65 if (wasPauseRequested())
6866 return;
6967
7068 uint *scanLine =
101101 if (allBlack && pass == 0) {
102102 pass = 4;
103103 } else {
104 if (!restart)
105 emit renderedImage(image, scaleFactor);
104 lockForWrite();
105 writable().image = image;
106 writable().scaleFactor = scaleFactor;
107 unlock();
106108 ++pass;
107109 }
108110 }
109
110 mutex.lock();
111 if (!restart)
112 condition.wait(&mutex);
113 restart = false;
114 mutex.unlock();
115 }
116}
117
118uint RenderThread::rgbFromWaveLength(double wave)
119{
120 double r = 0.0;
121 double g = 0.0;
122 double b = 0.0;
123
124 if (wave >= 380.0 && wave <= 440.0) {
125 r = -1.0 * (wave - 440.0) / (440.0 - 380.0);
126 b = 1.0;
127 } else if (wave >= 440.0 && wave <= 490.0) {
128 g = (wave - 440.0) / (490.0 - 440.0);
129 b = 1.0;
130 } else if (wave >= 490.0 && wave <= 510.0) {
131 g = 1.0;
132 b = -1.0 * (wave - 510.0) / (510.0 - 490.0);
133 } else if (wave >= 510.0 && wave <= 580.0) {
134 r = (wave - 510.0) / (580.0 - 510.0);
135 g = 1.0;
136 } else if (wave >= 580.0 && wave <= 645.0) {
137 r = 1.0;
138 g = -1.0 * (wave - 645.0) / (645.0 - 580.0);
139 } else if (wave >= 645.0 && wave <= 780.0) {
140 r = 1.0;
141 }
142
143 double s = 1.0;
144 if (wave > 700.0)
145 s = 0.3 + 0.7 * (780.0 - wave) / (780.0 - 700.0);
146 else if (wave < 420.0)
147 s = 0.3 + 0.7 * (wave - 380.0) / (420.0 - 380.0);
148
149 r = pow(r * s, 0.8);
150 g = pow(g * s, 0.8);
151 b = pow(b * s, 0.8);
152 return qRgb(int(r * 255), int(g * 255), int(b * 255));
111 emit done();
153112}
  
44** All rights reserved.
55** Contact: Nokia Corporation (qt-info@nokia.com)
66**
7** This file is part of the examples of the Qt Toolkit.
7** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/
88**
99** $QT_BEGIN_LICENSE:LGPL$
1010** No Commercial Usage
3939#include <QSize>
4040#include <QThread>
4141#include <QWaitCondition>
42#include <QImage>
43#include "thinkerqt/thinkerqt.h"
4244
43class QImage;
45class RenderThinker;
4446
45class RenderThread : public QThread
47class RenderThinkerData : public SnapshottableData
4648{
47 Q_OBJECT
49private:
50 friend class RenderThinker;
51 QImage image;
52 double scaleFactor;
4853
4954public:
50 RenderThread(QObject *parent = 0);
51 ~RenderThread();
55 RenderThinkerData ()
56 { }
5257
53 void render(double centerX, double centerY, double scaleFactor,
54 QSize resultSize);
58 RenderThinkerData (const RenderThinkerData& other)
59 : image (other.image),
60 scaleFactor(other.scaleFactor)
61 { }
5562
56signals:
57 void renderedImage(const QImage &image, double scaleFactor);
63 bool hasImage() const { return !image.isNull(); }
5864
65 const QImage& getImage() const { return image; }
66
67 double getScaleFactor() const { return scaleFactor; }
68};
69
70const int ColormapSize = 512;
71typedef uint Colormap[ColormapSize];
72
73class RenderThinker : public Thinker<RenderThinkerData>
74{
75 Q_OBJECT
76
77public:
78 RenderThinker(double centerX, double centerY, double scaleFactor,
79 QSize resultSize, const Colormap& colormap);
80
5981protected:
60 void run();
82 /* virtual*/ void start();
6183
6284private:
63 uint rgbFromWaveLength(double wave);
64
65 QMutex mutex;
66 QWaitCondition condition;
6785 double centerX;
6886 double centerY;
6987 double scaleFactor;
7088 QSize resultSize;
71 bool restart;
72 bool abort;
73
74 enum { ColormapSize = 512 };
75 uint colormap[ColormapSize];
89 const Colormap& colormap;
7690};
7791
7892#endif