Qt: Use MessagePainter with GL and Qt messages
Jeffrey Pfau jeffrey@endrift.com
Sat, 13 Jun 2015 02:55:33 -0700
7 files changed,
147 insertions(+),
56 deletions(-)
M
src/platform/qt/CMakeLists.txt
→
src/platform/qt/CMakeLists.txt
@@ -67,6 +67,7 @@ LoadSaveState.cpp
LogView.cpp MemoryModel.cpp MemoryView.cpp + MessagePainter.cpp MultiplayerController.cpp OverrideView.cpp PaletteView.cpp
M
src/platform/qt/DisplayGL.cpp
→
src/platform/qt/DisplayGL.cpp
@@ -135,8 +135,8 @@
PainterGL::PainterGL(QGLWidget* parent) : m_gl(parent) , m_active(false) - , m_messageTimer(this) , m_context(nullptr) + , m_messagePainter(nullptr) { GBAGLContextCreate(&m_backend); m_backend.d.swap = [](VideoBackend* v) {@@ -146,14 +146,6 @@ };
m_backend.d.user = this; m_backend.d.filter = false; m_backend.d.lockAspectRatio = false; - m_messageFont.setFamily("Source Code Pro"); - m_messageFont.setStyleHint(QFont::Monospace); - m_messageFont.setPixelSize(13); - connect(&m_messageTimer, SIGNAL(timeout()), this, SLOT(clearMessage())); - m_messageTimer.setSingleShot(true); - m_messageTimer.setInterval(5000); - - clearMessage(); } void PainterGL::setContext(GBAThread* context) {@@ -171,22 +163,8 @@ }
void PainterGL::resize(const QSize& size) { m_size = size; - int w = m_size.width(); - int h = m_size.height(); - int drawW = w; - int drawH = h; - if (m_backend.d.lockAspectRatio) { - if (w * 2 > h * 3) { - drawW = h * 3 / 2; - } else if (w * 2 < h * 3) { - drawH = w * 2 / 3; - } - } - m_world.reset(); - m_world.translate((w - drawW) / 2, (h - drawH) / 2); - m_world.scale(qreal(drawW) / VIDEO_HORIZONTAL_PIXELS, qreal(drawH) / VIDEO_VERTICAL_PIXELS); - m_message.prepare(m_world, m_messageFont); if (m_active) { + m_messagePainter->resize(size, m_backend.d.lockAspectRatio); forceDraw(); } }@@ -194,6 +172,7 @@
void PainterGL::lockAspectRatio(bool lock) { m_backend.d.lockAspectRatio = lock; if (m_active) { + m_messagePainter->resize(m_size, m_backend.d.lockAspectRatio); forceDraw(); } }@@ -206,6 +185,8 @@ }
} void PainterGL::start() { + m_messagePainter = new MessagePainter(this); + m_messagePainter->resize(m_size, m_backend.d.lockAspectRatio); m_gl->makeCurrent(); m_backend.d.init(&m_backend.d, reinterpret_cast<WHandle>(m_gl->winId())); m_gl->doneCurrent();@@ -239,6 +220,9 @@ m_backend.d.swap(&m_backend.d);
m_backend.d.deinit(&m_backend.d); m_gl->doneCurrent(); m_gl->context()->moveToThread(m_gl->thread()); + m_messagePainter->clearMessage(); + delete m_messagePainter; + m_messagePainter = nullptr; moveToThread(m_gl->thread()); }@@ -259,28 +243,9 @@ float r = m_gl->devicePixelRatio();
m_backend.d.resized(&m_backend.d, m_size.width() * r, m_size.height() * r); m_backend.d.drawFrame(&m_backend.d); m_painter.endNativePainting(); - m_painter.setWorldTransform(m_world); - m_painter.setRenderHint(QPainter::Antialiasing); - m_painter.setFont(m_messageFont); - m_painter.setPen(Qt::black); - m_painter.translate(1, VIDEO_VERTICAL_PIXELS - m_messageFont.pixelSize() - 1); - for (int i = 0; i < 16; ++i) { - m_painter.save(); - m_painter.translate(cos(i * M_PI / 8.0) * 0.8, sin(i * M_PI / 8.0) * 0.8); - m_painter.drawStaticText(0, 0, m_message); - m_painter.restore(); - } - m_painter.setPen(Qt::white); - m_painter.drawStaticText(0, 0, m_message); + m_messagePainter->paint(&m_painter); } void PainterGL::showMessage(const QString& message) { - m_message.setText(message); - m_message.prepare(m_world, m_messageFont); - m_messageTimer.stop(); - m_messageTimer.start(); -} - -void PainterGL::clearMessage() { - m_message.setText(QString()); + m_messagePainter->showMessage(message); }
M
src/platform/qt/DisplayGL.h
→
src/platform/qt/DisplayGL.h
@@ -8,8 +8,9 @@ #define QGBA_DISPLAY_GL
#include "Display.h" +#include "MessagePainter.h" + #include <QGLWidget> -#include <QStaticText> #include <QThread> #include <QTimer>@@ -86,21 +87,17 @@ void lockAspectRatio(bool lock);
void filter(bool filter); void showMessage(const QString& message); - void clearMessage(); private: void performDraw(); QPainter m_painter; - QStaticText m_message; QGLWidget* m_gl; bool m_active; - QTimer m_messageTimer; GBAThread* m_context; GBAGLContext m_backend; QSize m_size; - QTransform m_world; - QFont m_messageFont; + MessagePainter* m_messagePainter; }; }
M
src/platform/qt/DisplayQt.cpp
→
src/platform/qt/DisplayQt.cpp
@@ -46,6 +46,10 @@ m_backing = QImage(reinterpret_cast<const uchar*>(buffer), 256, 256, QImage::Format_RGB32);
#endif } +void DisplayQt::showMessage(const QString& message) { + m_messagePainter.showMessage(message); +} + void DisplayQt::paintEvent(QPaintEvent*) { QPainter painter(this); painter.fillRect(QRect(QPoint(), size()), Qt::black);@@ -54,10 +58,12 @@ painter.setRenderHint(QPainter::SmoothPixmapTransform);
} QSize s = size(); QSize ds = s; - if (s.width() * 2 > s.height() * 3) { - ds.setWidth(s.height() * 3 / 2); - } else if (s.width() * 2 < s.height() * 3) { - ds.setHeight(s.width() * 2 / 3); + if (m_lockAspectRatio) { + if (s.width() * 2 > s.height() * 3) { + ds.setWidth(s.height() * 3 / 2); + } else if (s.width() * 2 < s.height() * 3) { + ds.setHeight(s.width() * 2 / 3); + } } QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2); QRect full(origin, ds);@@ -67,4 +73,9 @@ painter.drawImage(full, m_backing, QRect(0, 0, 240, 160));
#else painter.drawImage(full, m_backing.rgbSwapped(), QRect(0, 0, 240, 160)); #endif + m_messagePainter.paint(&painter); +} + +void DisplayQt::resizeEvent(QResizeEvent*) { + m_messagePainter.resize(size(), m_lockAspectRatio); }
M
src/platform/qt/DisplayQt.h
→
src/platform/qt/DisplayQt.h
@@ -7,6 +7,7 @@ #ifndef QGBA_DISPLAY_QT
#define QGBA_DISPLAY_QT #include "Display.h" +#include "MessagePainter.h" #include <QImage> #include <QTimer>@@ -31,15 +32,17 @@ void lockAspectRatio(bool lock) override;
void filter(bool filter) override; void framePosted(const uint32_t*) override; - void showMessage(const QString& message) override {}; + void showMessage(const QString& message) override; protected: virtual void paintEvent(QPaintEvent*) override; + virtual void resizeEvent(QResizeEvent*) override;; private: QImage m_backing; bool m_lockAspectRatio; bool m_filter; + MessagePainter m_messagePainter; }; }
A
src/platform/qt/MessagePainter.cpp
@@ -0,0 +1,77 @@
+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "MessagePainter.h" + +#include <QPainter> + +#include <QDebug> + +extern "C" { +#include "gba/video.h" +} + +using namespace QGBA; + +MessagePainter::MessagePainter(QObject* parent) + : QObject(parent) + , m_messageTimer(this) +{ + m_messageFont.setFamily("Source Code Pro"); + m_messageFont.setStyleHint(QFont::Monospace); + m_messageFont.setPixelSize(13); + connect(&m_messageTimer, SIGNAL(timeout()), this, SLOT(clearMessage())); + m_messageTimer.setSingleShot(true); + m_messageTimer.setInterval(5000); + + clearMessage(); +} + +void MessagePainter::resize(const QSize& size, bool lockAspectRatio) { + int w = size.width(); + int h = size.height(); + int drawW = w; + int drawH = h; + if (lockAspectRatio) { + if (w * 2 > h * 3) { + drawW = h * 3 / 2; + } else if (w * 2 < h * 3) { + drawH = w * 2 / 3; + } + } + m_world.reset(); + m_world.translate((w - drawW) / 2, (h - drawH) / 2); + m_world.scale(qreal(drawW) / VIDEO_HORIZONTAL_PIXELS, qreal(drawH) / VIDEO_VERTICAL_PIXELS); + m_message.prepare(m_world, m_messageFont); +} + +void MessagePainter::paint(QPainter* painter) { + painter->setWorldTransform(m_world); + painter->setRenderHint(QPainter::Antialiasing); + painter->setFont(m_messageFont); + painter->setPen(Qt::black); + painter->translate(1, VIDEO_VERTICAL_PIXELS - m_messageFont.pixelSize() - 1); + const static int ITERATIONS = 11; + for (int i = 0; i < ITERATIONS; ++i) { + painter->save(); + painter->translate(cos(i * 2.0 * M_PI / ITERATIONS) * 0.8, sin(i * 2.0 * M_PI / ITERATIONS) * 0.8); + painter->drawStaticText(0, 0, m_message); + painter->restore(); + } + painter->setPen(Qt::white); + painter->drawStaticText(0, 0, m_message); +} + +void MessagePainter::showMessage(const QString& message) { + m_message.setText(message); + m_message.prepare(m_world, m_messageFont); + m_messageTimer.stop(); + m_messageTimer.start(); +} + +void MessagePainter::clearMessage() { + m_message.setText(QString()); + m_messageTimer.stop(); +}
A
src/platform/qt/MessagePainter.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef QGBA_MESSAGE_PAINTER +#define QGBA_MESSAGE_PAINTER + +#include <QObject> +#include <QStaticText> +#include <QTimer> + +namespace QGBA { + +class MessagePainter : public QObject { +Q_OBJECT + +public: + MessagePainter(QObject* parent = nullptr); + + void resize(const QSize& size, bool lockAspectRatio); + void paint(QPainter* painter); + +public slots: + void showMessage(const QString& message); + void clearMessage(); + +private: + QStaticText m_message; + QTimer m_messageTimer; + QTransform m_world; + QFont m_messageFont; +}; + +} + +#endif