+++ /dev/null
-#include <DrawingArea.h>
-
-DrawingArea::DrawingArea(int width, int height)
-{
- image = new QImage(width, height, QImage::Format_RGB32);
- image->fill(QColor(Qt::white).rgb());
- painter = new QPainter(image);
- setDirty();
-}
-
-DrawingArea::~DrawingArea()
-{
- delete painter;
- delete image;
-}
-
-void DrawingArea::setColor(const QColor &color)
-{
- QPen pen(painter->pen());
- pen.setColor(color);
- painter->setPen(pen);
-}
-
-void DrawingArea::setColor(float red, float green, float blue)
-{
- QColor color;
- color.setRgbF(red, green, blue);
- this->setColor(color);
-}
-
-void DrawingArea::drawPoint(int x, int y)
-{
- lock();
- painter->drawPoint(x, y);
- setDirty(QRect(x, y, 1, 1));
- unlock();
-}
-
-void DrawingArea::drawLine(int x1, int y1, int x2, int y2)
-{
- lock();
- painter->drawLine(x1, y1, x2, y2);
- if (x1 > x2)
- std::swap(x1, x2);
- if (y1 > y2)
- std::swap(y1, y2);
- setDirty(QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1));
- unlock();
-}
-
-void DrawingArea::setDirty()
-{
- setDirty(QRect(0, 0, width(), height()));
-}
-
-void DrawingArea::setDirty(const QRect &rect)
-{
- if (dirtyFlag)
- dirtyRect |= rect;
- else
- dirtyRect = rect;
- dirtyFlag = true;
-}
-
-void DrawingArea::setClean()
-{
- dirtyFlag = false;
-}
-
+++ /dev/null
-#ifndef DRAWING_AREA_H
-#define DRAWING_AREA_H
-
-#include <QColor>
-#include <QImage>
-#include <QObject>
-#include <QPainter>
-#include <QRect>
-#include <QSize>
-#include <QMutex>
-
-class DrawingArea: public QObject {
-/* Q_OBJECT */
-
-public:
- static const int DEFAULT_WIDTH = 640;
- static const int DEFAULT_HEIGHT = 480;
-
- DrawingArea(int width = DEFAULT_WIDTH, int height = DEFAULT_HEIGHT);
- ~DrawingArea();
-
- int width() const;
- int height() const;
- const QSize size() const;
-
- void setColor(const QColor &color);
- void setColor(float red, float green, float blue);
-
- void drawPoint(int x, int y);
- void drawLine(int x1, int y1, int x2, int y2);
-
- QImage &getImage();
-
- bool isDirty() const;
- void setDirty();
- void setDirty(const QRect &rect);
- void setClean();
-
- QRect getDirtyRect() const;
-
- void lock();
- void unlock();
-
-private:
- QImage *image;
- QPainter *painter;
- bool dirtyFlag;
- QRect dirtyRect;
- QMutex mutex;
-};
-
-inline
-int DrawingArea::width() const
-{
- return image->width();
-}
-
-inline
-int DrawingArea::height() const
-{
- return image->height();
-}
-
-inline
-const QSize DrawingArea::size() const
-{
- return image->size();
-}
-
-inline
-QImage &DrawingArea::getImage()
-{
- return *image;
-}
-
-inline
-bool DrawingArea::isDirty() const
-{
- return dirtyFlag;
-}
-
-inline
-QRect DrawingArea::getDirtyRect() const
-{
- return dirtyRect;
-}
-
-inline
-void DrawingArea::lock()
-{
- mutex.lock();
-}
-
-inline
-void DrawingArea::unlock()
-{
- mutex.unlock();
-}
-
-#endif // !DRAWING_AREA_H
+++ /dev/null
-#include "DrawingThread.h"
-#include <QThread>
-
-DrawingThread::DrawingThread(DrawingArea &a, ThreadFunction f)
- : drawingArea(a)
- , threadFunction(f)
-{
-}
-
-void DrawingThread::run()
-{
- exit(threadFunction(drawingArea));
-}
+++ /dev/null
-#ifndef DRAWING_THREAD_H
-#define DRAWING_THREAD_H
-
-#include "DrawingArea.h"
-#include <QThread>
-
-class DrawingThread: public QThread {
-public:
- typedef int (*ThreadFunction)(DrawingArea &);
-
- DrawingThread(DrawingArea &a, ThreadFunction f);
-
- void run();
-
-private:
- DrawingArea &drawingArea;
- ThreadFunction threadFunction;
-
-};
-
-#endif // !DRAWING_THREAD_H
#include "DrawingWindow.h"
-#include <QPainter>
#include <QPaintEvent>
+#include <QThread>
+#include <QTimerEvent>
-#include <iostream>
+class DrawingWindow::DrawingThread: public QThread {
+public:
+ DrawingThread(DrawingWindow &w, ThreadFunction f)
+ : drawingWindow(w)
+ , threadFunction(f)
+ {
+ }
+
+ void run()
+ {
+ exit(threadFunction(drawingWindow));
+ }
-DrawingWindow::DrawingWindow(DrawingArea &a)
+private:
+ DrawingWindow &drawingWindow;
+ ThreadFunction threadFunction;
+
+};
+
+DrawingWindow::DrawingWindow(ThreadFunction fun, int width, int height)
: QWidget()
- , drawingArea(a)
- , pixmap(a.size())
{
- initialize();
+ initialize(fun, width, height);
}
-DrawingWindow::DrawingWindow(QWidget *parent, DrawingArea &a)
+DrawingWindow::DrawingWindow(QWidget *parent,
+ ThreadFunction fun, int width, int height)
: QWidget(parent)
- , drawingArea(a)
- , pixmap(a.size())
{
- initialize();
+ initialize(fun, width, height);
}
DrawingWindow::DrawingWindow(QWidget *parent, Qt::WindowFlags flags,
- DrawingArea &a)
+ ThreadFunction fun, int width, int height)
: QWidget(parent, flags)
- , drawingArea(a)
- , pixmap(a.size())
{
- initialize();
+ initialize(fun, width, height);
+}
+
+void DrawingWindow::initialize(ThreadFunction fun, int width, int height)
+{
+ image = new QImage(width, height, QImage::Format_RGB32);
+ image->fill(QColor(Qt::white).rgb());
+
+ painter = new QPainter(image);
+
+#ifdef USE_PIXMAP_CACHE
+ pixmap = new QPixmap(image->size());
+ QPainter pixmapPainter(pixmap);
+ pixmapPainter.drawImage(0, 0, *image);
+#endif
+
+ dirtyFlag = false;
+
+ setFocusPolicy(Qt::StrongFocus);
+ setFixedSize(image->size());
+ setAttribute(Qt::WA_OpaquePaintEvent);
+ setFocus();
+ timer.start(paintInterval, this);
+
+ thread = new DrawingThread(*this, fun);
+ thread_started = false;
+}
+
+DrawingWindow::~DrawingWindow()
+{
+ delete thread;
+#ifdef USE_PIXMAP_CACHE
+ delete pixmap;
+#endif
+ delete painter;
+ delete image;
+}
+
+void DrawingWindow::setColor(const QColor &color)
+{
+ QPen pen(painter->pen());
+ pen.setColor(color);
+ painter->setPen(pen);
+}
+
+void DrawingWindow::setColor(float red, float green, float blue)
+{
+ QColor color;
+ color.setRgbF(red, green, blue);
+ this->setColor(color);
+}
+
+void DrawingWindow::drawPoint(int x, int y)
+{
+ lock();
+ painter->drawPoint(x, y);
+ setDirtyRect(x, y);
+ unlock();
+}
+
+void DrawingWindow::drawLine(int x1, int y1, int x2, int y2)
+{
+ lock();
+ painter->drawLine(x1, y1, x2, y2);
+ setDirtyRect(x1, y1, x2, y2);
+ unlock();
}
void DrawingWindow::paintEvent(QPaintEvent *ev)
{
+ QPainter widgetPainter(this);
QRect rect = ev->rect();
- drawingArea.lock();
- if (drawingArea.isDirty()) {
- QPainter pixmapPainter(&pixmap);
- pixmapPainter.drawImage(drawingArea.getDirtyRect(),
- drawingArea.getImage(),
- drawingArea.getDirtyRect());
- drawingArea.setClean();
- rect |= drawingArea.getDirtyRect();
+#ifdef USE_PIXMAP_CACHE
+ widgetPainter.drawPixmap(rect, *pixmap, rect);
+#else
+ lock();
+ widgetPainter.drawImage(rect, *image, rect);
+ unlock();
+#endif
+}
+
+void DrawingWindow::showEvent(QShowEvent *ev)
+{
+ if (!thread_started) {
+ thread->start();
+ thread_started = true;
}
- drawingArea.unlock();
- QPainter painter(this);
- painter.drawPixmap(0, 0, pixmap);
+ QWidget::showEvent(ev);
}
void DrawingWindow::timerEvent(QTimerEvent *ev)
{
if (ev->timerId() == timer.timerId()) {
- update();
+ lock();
+ if (dirtyFlag) {
+#ifdef USE_PIXMAP_CACHE
+ QPainter pixmapPainter(pixmap);
+ pixmapPainter.drawImage(dirtyRect, *image, dirtyRect);
+#endif
+ dirtyFlag = false;
+ update(dirtyRect);
+ timer.start(paintInterval, this);
+ }
+ unlock();
} else {
QWidget::timerEvent(ev);
}
}
-void DrawingWindow::initialize()
+void DrawingWindow::setDirtyRect()
{
- setFocusPolicy(Qt::StrongFocus);
- setFixedSize(drawingArea.getImage().size());
- setAttribute(Qt::WA_OpaquePaintEvent);
- timer.start(50, this);
+ setDirtyRect(QRect(0, 0, width(), height()));
+}
+
+void DrawingWindow::setDirtyRect(int x, int y)
+{
+ setDirtyRect(QRect(x, y, 1, 1));
+}
+
+void DrawingWindow::setDirtyRect(int x1, int y1, int x2, int y2)
+{
+ QRect r;
+ r.setCoords(x1, y1, x2, y2);
+ setDirtyRect(r.normalized());
+}
+
+void DrawingWindow::setDirtyRect(const QRect &rect)
+{
+ if (dirtyFlag) {
+ dirtyRect |= rect;
+ } else {
+ dirtyFlag = true;
+ dirtyRect = rect;
+ }
}
#ifndef DRAWING_WINDOW_H
#define DRAWING_WINDOW_H
-#include "DrawingArea.h"
-#include <QPixmap>
-#include <QTimer>
+#define USE_PIXMAP_CACHE
+
+#include <QBasicTimer>
+#include <QColor>
+#include <QImage>
+#include <QMutex>
+#include <QPainter>
+#ifdef USE_PIXMAP_CACHE
+# include <QPixmap>
+#endif
+#include <QRect>
#include <QWidget>
+#include <Qt>
class DrawingWindow: public QWidget {
/* Q_OBJECT */
public:
- DrawingWindow(DrawingArea &a);
- DrawingWindow(QWidget *parent, DrawingArea &a);
- DrawingWindow(QWidget *parent, Qt::WindowFlags flags, DrawingArea &a);
+ typedef int (*ThreadFunction)(DrawingWindow &);
+
+ static const int DEFAULT_WIDTH = 640;
+ static const int DEFAULT_HEIGHT = 480;
+
+ DrawingWindow(ThreadFunction fun,
+ int width = DEFAULT_WIDTH, int height = DEFAULT_HEIGHT);
+ DrawingWindow(QWidget *parent,
+ ThreadFunction fun,
+ int width = DEFAULT_WIDTH, int height = DEFAULT_HEIGHT);
+ DrawingWindow(QWidget *parent, Qt::WindowFlags flags,
+ ThreadFunction fun,
+ int width = DEFAULT_WIDTH, int height = DEFAULT_HEIGHT);
+
+ ~DrawingWindow();
+
+ int width() const;
+ int height() const;
+
+ void setColor(float red, float green, float blue);
+ void setColor(const QColor &color);
+
+ void drawPoint(int x, int y);
+ void drawLine(int x1, int y1, int x2, int y2);
protected:
void paintEvent(QPaintEvent *ev);
+ void showEvent(QShowEvent *ev);
void timerEvent(QTimerEvent *ev);
private:
- DrawingArea &drawingArea;
- QPixmap pixmap;
+ class DrawingThread;
+
+ static const int paintInterval = 33;
+
QBasicTimer timer;
- void initialize();
+ QImage *image;
+ QPainter *painter;
+#ifdef USE_PIXMAP_CACHE
+ QPixmap *pixmap;
+#endif
+
+ DrawingThread *thread;
+ bool thread_started;
+
+ bool dirtyFlag;
+ QRect dirtyRect;
+
+ QMutex mutex;
+
+ void initialize(ThreadFunction fun, int width, int height);
+
+ void lock();
+ void unlock();
+
+ void setDirtyRect();
+ void setDirtyRect(int x, int y);
+ void setDirtyRect(int x1, int y1, int x2, int y2);
+ void setDirtyRect(const QRect &rect);
};
+inline
+int DrawingWindow::width() const
+{
+ return image->width();
+}
+
+inline
+int DrawingWindow::height() const
+{
+ return image->height();
+}
+
+inline
+void DrawingWindow::lock()
+{
+ mutex.lock();
+}
+
+inline
+void DrawingWindow::unlock()
+{
+ mutex.unlock();
+}
+
#endif // !DRAWING_WINDOW_H
#include <QApplication>
-#include <DrawingArea.h>
-#include <DrawingThread.h>
#include <DrawingWindow.h>
#include <iostream>
-int main_drawing_thread(DrawingArea &a)
+int flip(DrawingWindow &w)
{
- std::cout << "[ " << a.width() << " x " << a.height() << " ]\n";
+ std::cout << "[ " << w.width() << " x " << w.height() << " ]\n";
int c = 0;
int y = 0;
- int h = a.height();
- int w = a.width();
- int count = 10;
+// int h = w.height();
+// int w = w.width();
+ int count = 50;//1 << 31;
while (1) {
// std::cerr << "loooooooooooooooooooooop "
// << y << " (" << c << ")\n";
- a.setColor(c, c, c);
+ w.setColor(c, c, c);
for (int yy = y; yy < y + 10; yy++)
- for (int x = 0; x < w; x++)
- a.drawPoint(x, yy);
- if ((y += 10) >= h) {
+ for (int x = 0; x < w.width(); x++)
+ w.drawPoint(x, yy);
+ if ((y += 10) >= w.height()) {
y = 0;
c = !c;
if (!--count) break;
- std::cerr << "loooooooooooooooooooooop "
- << y << " (" << c << ")\n";
+// std::cerr << "loooooooooooooooooooooop "
+// << y << " (" << c << ")\n";
}
}
return 0;
}
+int mandel(DrawingWindow &w)
+{
+ /* paramètres par défaut */
+ int larg = w.width();
+ int haut = w.height();
+ float Rmin = -2.05;
+ float Rmax = 0.55;
+ float Imin = -1.3;
+ float Imax = 1.3;
+
+ int maxiter = 100;
+
+ int x, y; /* le pixel considéré */
+ float cr, ci; /* le complexe correspondant */
+ float zr, zi; /* pour calculer la suite */
+ float zr2, zi2;
+ float pr, pi; /* taille d'un pixel */
+ float rouge, vert, bleu;
+ int i;
+
+ pr = (Rmax - Rmin) / larg;
+ pi = (Imax - Imin) / haut;
+
+ cr = Rmin;
+ for (x = 0; x < larg; x++) {
+ ci = Imin;
+ for (y = 0; y < haut; y++) {
+ /* z_1 = c */
+ zr = cr;
+ zi = ci;
+ for (i = 1; i <= maxiter; i++) {
+ zr2 = zr * zr;
+ zi2 = zi * zi;
+ if (zr2 + zi2 >= 4) {
+ /* |z| >= 2 : on sort de la boucle */
+ break;
+ }
+ /* on calcule le z suivant */
+ zi = 2*zr*zi + ci;
+ zr = zr2 - zi2 + cr;
+ }
+ /* on est sorti trop tôt du for(...):
+ on affiche le pixel d'un couleur en fonction
+ de i */
+ if (i <= maxiter / 2) {
+ /* entre rouge et vert */
+ vert = (2.0 * i) / maxiter;
+ rouge = 1.0 - vert;
+ bleu = 0.0;
+ } else if (i <= maxiter) {
+ /* entre vert et bleu */
+ rouge = 0.0;
+ bleu = (2.0 * i) / maxiter - 1.0;
+ vert = 1.0 - bleu;
+ } else /* (i > maxiter) */
+ rouge = vert = bleu = 0.0;
+ w.setColor(rouge, vert, bleu);
+ w.drawPoint(x, y);
+
+ ci += pi;
+ }
+ cr += pr;
+ }
+ return 0;
+}
+
int main(int argc, char *argv[])
{
+ const int nf = 1;
+ const int nm = 1;
+ const int w = 1000;
+ const int h = 700;
QApplication application(argc, argv);
- DrawingArea drawingArea(800, 600);
- DrawingWindow drawingWindow(drawingArea);
- DrawingThread drawingThread(drawingArea, main_drawing_thread);
+ DrawingWindow *dw[nf + nm];
+
+ for (int i = 0; i < nf; ++i)
+ dw[i] = new DrawingWindow(flip, w, h);
+ for (int i = nf; i < nf + nm; ++i)
+ dw[i] = new DrawingWindow(mandel, w, h);
- drawingWindow.show();
- drawingThread.start();
+ for (int i = 0; i < nf + nm; ++i)
+ dw[i]->show();
return application.exec();
}
CONFIG += qt debug
-QMAKE_CFLAGS += -O2
-QMAKE_CXXFLAGS += -O2
+QMAKE_CFLAGS += -O3
+QMAKE_CXXFLAGS += -O3
QMAKE_CFLAGS += -pg
QMAKE_CXXFLAGS += -pg
QMAKE_LFLAGS += -pg
-HEADERS += DrawingArea.h \
- DrawingThread.h \
- DrawingWindow.h
+HEADERS += DrawingWindow.h
-SOURCES += DrawingArea.cpp \
- DrawingThread.cpp \
- DrawingWindow.cpp \
+SOURCES += DrawingWindow.cpp \
hello.cc