Skip to content

Commit

Permalink
Improve color contrast for lighter themes.
Browse files Browse the repository at this point in the history
Also, respond to palette updates when the theme is changed.
  • Loading branch information
bmatherly committed Feb 26, 2015
1 parent da36da1 commit 51a06d7
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 60 deletions.
57 changes: 24 additions & 33 deletions src/widgets/scopes/audiowaveformscopewidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,13 @@ static int graphCenterY(const QSize& widgetSize, int channel, int maxChan, int p
AudioWaveformScopeWidget::AudioWaveformScopeWidget()
: ScopeWidget("AudioWaveform")
, m_frame()
, m_prevSize(0, 0)
, m_renderWave()
, m_refreshTime()
, m_graphTopPadding(0)
, m_channels(0)
, m_mutex(QMutex::NonRecursive)
, m_displayWave()
, m_displayGrid()
, m_size(0, 0)
{
qDebug() << "begin";
setAutoFillBackground(true);
Expand All @@ -70,54 +68,60 @@ AudioWaveformScopeWidget::AudioWaveformScopeWidget()

AudioWaveformScopeWidget::~AudioWaveformScopeWidget()
{
qDebug() << "begin";
qDebug() << "end";
}

void AudioWaveformScopeWidget::refreshScope()
void AudioWaveformScopeWidget::refreshScope(const QSize& size, bool full)
{
m_mutex.lock();
QSize currentSize = m_size;
QSize prevSize = m_displayWave.size();
m_mutex.unlock();

while (m_queue.count() > 0) {
m_frame = m_queue.pop();
}

// Check if a full refresh should be forced.
int channels = m_frame.get_audio_channels();
channels = channels ? channels : 2;
if (prevSize != size || channels != m_channels) {
m_channels = channels;
full = true;
}

if (m_prevSize == currentSize && m_refreshTime.elapsed() < 90) {
// When not resizing, limit refreshes to 90ms.
if (!full && m_refreshTime.elapsed() < 90) {
// Limit refreshes to 90ms unless there is a good reason.
return;
}

if (m_prevSize != currentSize || channels != m_channels) {
m_channels = channels;
createGrid(currentSize);
if (full) {
createGrid(size);
}

if (m_renderWave.size() != currentSize) {
m_renderWave = QImage(currentSize, QImage::Format_ARGB32_Premultiplied);
if (m_renderWave.size() != size) {
m_renderWave = QImage(size, QImage::Format_ARGB32_Premultiplied);
}

m_renderWave.fill(Qt::transparent);

QPainter p(&m_renderWave);
p.setRenderHint(QPainter::Antialiasing, true);
p.setPen(palette().dark().color().rgb());
QColor penColor(palette().text().color());
penColor.setAlpha(255/2);
QPen pen(penColor);
pen.setWidth(0);
p.setPen(pen);

if (m_frame.is_valid() && m_frame.get_audio_samples() > 0) {

int samples = m_frame.get_audio_samples();
int16_t* audio = (int16_t*)m_frame.get_audio();
int waveAmplitude = graphHeight(currentSize, m_channels, m_graphTopPadding) / 2;
int waveAmplitude = graphHeight(size, m_channels, m_graphTopPadding) / 2;
qreal scaleFactor = (qreal)waveAmplitude / (qreal)MAX_AMPLITUDE;

for (int c = 0; c < m_channels; c++)
{
p.save();
int y = graphCenterY(currentSize, c, m_channels, m_graphTopPadding);
int y = graphCenterY(size, c, m_channels, m_graphTopPadding);
p.translate(0, y);

// For each x position on the waveform, find the min and max sample
Expand All @@ -132,7 +136,7 @@ void AudioWaveformScopeWidget::refreshScope()

for (int i = 0; i <= samples; i++)
{
int x = ( i * currentSize.width() ) / samples;
int x = ( i * size.width() ) / samples;
if (x != lastX) {
// The min and max have been determined for the previous x
// So draw the line
Expand All @@ -156,7 +160,7 @@ void AudioWaveformScopeWidget::refreshScope()

if (*q > max) max = *q;
if (*q < min) min = *q;
q += channels;
q += m_channels;
}
p.restore();
}
Expand All @@ -168,7 +172,6 @@ void AudioWaveformScopeWidget::refreshScope()
m_displayWave.swap(m_renderWave);
m_mutex.unlock();

m_prevSize = currentSize;
m_refreshTime.restart();
}

Expand All @@ -190,11 +193,7 @@ void AudioWaveformScopeWidget::createGrid(const QSize& size)
m_displayGrid = QImage(size, QImage::Format_ARGB32_Premultiplied);
m_displayGrid.fill(Qt::transparent);
QPainter p(&m_displayGrid);
QColor penColor(palette().text().color());
penColor.setAlpha(255/2);
QPen pen(penColor);
pen.setWidth(0);
p.setPen(pen);
p.setPen(palette().text().color().rgb());
p.setFont(font);

for (int c = 0; c < m_channels; c++) {
Expand Down Expand Up @@ -240,20 +239,12 @@ void AudioWaveformScopeWidget::paintEvent(QPaintEvent*)

QPainter p(this);
m_mutex.lock();
p.drawImage(rect(), m_displayWave, m_displayWave.rect());
p.drawImage(rect(), m_displayGrid, m_displayGrid.rect());
p.drawImage(rect(), m_displayWave, m_displayWave.rect());
m_mutex.unlock();
p.end();
}

void AudioWaveformScopeWidget::resizeEvent(QResizeEvent*)
{
m_mutex.lock();
m_size = size();
m_mutex.unlock();
requestRefresh();
}

QString AudioWaveformScopeWidget::getTitle()
{
return tr("Audio Waveform");
Expand Down
5 changes: 1 addition & 4 deletions src/widgets/scopes/audiowaveformscopewidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,14 @@ class AudioWaveformScopeWidget Q_DECL_FINAL : public ScopeWidget

private:
// Functions run in scope thread.
void refreshScope() Q_DECL_OVERRIDE;
void refreshScope(const QSize& size, bool full) Q_DECL_OVERRIDE;
void createGrid(const QSize& size);

// Functions run in GUI thread.
void paintEvent(QPaintEvent*) Q_DECL_OVERRIDE;
void resizeEvent(QResizeEvent*) Q_DECL_OVERRIDE;

// Members accessed only in scope thread (no thread protection).
SharedFrame m_frame;
QSize m_prevSize;
QImage m_renderWave;
QTime m_refreshTime;
int m_graphTopPadding;
Expand All @@ -55,7 +53,6 @@ class AudioWaveformScopeWidget Q_DECL_FINAL : public ScopeWidget
QMutex m_mutex;
QImage m_displayWave;
QImage m_displayGrid;
QSize m_size;
};

#endif // AUDIOWAVEFORMSCOPEWIDGET_H
31 changes: 30 additions & 1 deletion src/widgets/scopes/scopewidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ ScopeWidget::ScopeWidget(const QString& name)
, m_queue(3, DataQueue<SharedFrame>::OverflowModeDiscardOldest)
, m_future()
, m_refreshPending(false)
, m_mutex(QMutex::NonRecursive)
, m_forceRefresh(false)
, m_size(0, 0)
{
qDebug() << "begin" << m_future.isFinished();
setObjectName(name);
Expand Down Expand Up @@ -52,8 +55,18 @@ void ScopeWidget::requestRefresh()

void ScopeWidget::refreshInThread()
{
if (m_size.isEmpty()) {
return;
}

m_mutex.lock();
QSize size = m_size;
bool full = m_forceRefresh;
m_forceRefresh = false;
m_mutex.unlock();

m_refreshPending = false;
refreshScope();
refreshScope(size, full);
// Tell the GUI thread that the refresh is complete.
QMetaObject::invokeMethod(this, "onRefreshThreadComplete", Qt::QueuedConnection);
}
Expand All @@ -65,3 +78,19 @@ void ScopeWidget::onRefreshThreadComplete()
requestRefresh();
}
}

void ScopeWidget::resizeEvent(QResizeEvent*)
{
m_mutex.lock();
m_size = size();
m_mutex.unlock();
requestRefresh();
}

void ScopeWidget::changeEvent(QEvent*)
{
m_mutex.lock();
m_forceRefresh = true;
m_mutex.unlock();
requestRefresh();
}
10 changes: 9 additions & 1 deletion src/widgets/scopes/scopewidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <QDebug>
#include <QThread>
#include <QFuture>
#include <QMutex>
#include "sharedframe.h"
#include "dataqueue.h"

Expand Down Expand Up @@ -94,7 +95,7 @@ public slots:
protect any members that may be accessed concurrently by the refresh
thread and the GUI thread.
*/
virtual void refreshScope() = 0;
virtual void refreshScope(const QSize& size, bool full) = 0;

/*!
Stores frames received by onNewFrame().
Expand All @@ -105,10 +106,17 @@ public slots:
DataQueue<SharedFrame> m_queue;

private:
void resizeEvent(QResizeEvent*) Q_DECL_OVERRIDE;
void changeEvent(QEvent*) Q_DECL_OVERRIDE;
Q_INVOKABLE void onRefreshThreadComplete() Q_DECL_FINAL;
void refreshInThread() Q_DECL_FINAL;
QFuture<void> m_future;
bool m_refreshPending;

// Members accessed in multiple threads (mutex protected).
QMutex m_mutex;
bool m_forceRefresh;
QSize m_size;
};

#endif // SCOPEWIDGET_H
21 changes: 3 additions & 18 deletions src/widgets/scopes/videowaveformscopewidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,25 @@
VideoWaveformScopeWidget::VideoWaveformScopeWidget()
: ScopeWidget("VideoZoom")
, m_frame()
, m_prevSize(0, 0)
, m_renderImg()
, m_refreshTime()
, m_mutex(QMutex::NonRecursive)
, m_displayImg()
, m_size(0, 0)
{
qDebug() << "begin";
m_refreshTime.start();
qDebug() << "end";
}


void VideoWaveformScopeWidget::refreshScope()
void VideoWaveformScopeWidget::refreshScope(const QSize& size, bool full)
{
m_mutex.lock();
QSize currentSize = m_size;
m_mutex.unlock();

while (m_queue.count() > 0) {
m_frame = m_queue.pop();
}

if (m_prevSize == currentSize && m_refreshTime.elapsed() < 90) {
// When not resizing, limit refreshes to 90ms.
if (!full && m_refreshTime.elapsed() < 90) {
// Limit refreshes to 90ms unless there is a good reason.
return;
}

Expand Down Expand Up @@ -79,7 +73,6 @@ void VideoWaveformScopeWidget::refreshScope()
m_displayImg.swap(m_renderImg);
m_mutex.unlock();

m_prevSize = currentSize;
m_refreshTime.restart();
}

Expand All @@ -99,14 +92,6 @@ void VideoWaveformScopeWidget::paintEvent(QPaintEvent*)
p.end();
}

void VideoWaveformScopeWidget::resizeEvent(QResizeEvent*)
{
m_mutex.lock();
m_size = size();
m_mutex.unlock();
requestRefresh();
}

QString VideoWaveformScopeWidget::getTitle()
{
return tr("Video Waveform");
Expand Down
4 changes: 1 addition & 3 deletions src/widgets/scopes/videowaveformscopewidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ class VideoWaveformScopeWidget Q_DECL_FINAL : public ScopeWidget
QString getTitle();

private:
void refreshScope() Q_DECL_OVERRIDE;
void refreshScope(const QSize& size, bool full) Q_DECL_OVERRIDE;
void paintEvent(QPaintEvent*) Q_DECL_OVERRIDE;
void resizeEvent(QResizeEvent*) Q_DECL_OVERRIDE;

SharedFrame m_frame;
QSize m_prevSize;
Expand All @@ -45,7 +44,6 @@ class VideoWaveformScopeWidget Q_DECL_FINAL : public ScopeWidget
// Variables accessed from multiple threads (mutex protected)
QMutex m_mutex;
QImage m_displayImg;
QSize m_size;
};

#endif // VIDEOWAVEFORMSCOPEWIDGET_H

0 comments on commit 51a06d7

Please sign in to comment.