From 887f6426bd58f1bfd2bc38d1a2b57f1f4be5edbc Mon Sep 17 00:00:00 2001 From: "Tim E. Real" Date: Fri, 1 Mar 2013 03:36:47 +0000 Subject: Wave Editor: Fixed some painting problems. Optimizations, speed boosts. --- muse2/ChangeLog | 2 + muse2/muse/helper.cpp | 54 +++++++++ muse2/muse/helper.h | 4 +- muse2/muse/waveedit/wavecanvas.cpp | 219 ++++++++++++++++++++++--------------- muse2/muse/widgets/canvas.cpp | 4 +- 5 files changed, 194 insertions(+), 89 deletions(-) (limited to 'muse2') diff --git a/muse2/ChangeLog b/muse2/ChangeLog index 83ad8da6..d6b03f1a 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,5 @@ +28.02.2013: + - Wave Editor: Fixed some painting problems. Optimizations, speed boosts. (Tim) 24.02.2013: - Improved dark theme, midi editors now set background color, the current part of the ruler is darker. Theme setting separated from the regular Ok button in the Appearance settings. Also fixed the color diff --git a/muse2/muse/helper.cpp b/muse2/muse/helper.cpp index 2a6992fc..c50fb66d 100644 --- a/muse2/muse/helper.cpp +++ b/muse2/muse/helper.cpp @@ -49,6 +49,8 @@ #include #include #include +#include +#include using std::set; @@ -1099,6 +1101,58 @@ int populateMidiCtrlMenu(PopupMenu* menu, MusECore::PartList* part_list, MusECor return est_width; } +//--------------------------------------------------- +// clipQLine +//--------------------------------------------------- + +QLine clipQLine(int x1, int y1, int x2, int y2, const QRect& rect) +{ + const int rect_x = rect.x(); + const int rect_y = rect.y(); + const int rect_right = rect_x + rect.width(); + const int rect_bot = rect_y + rect.height(); + + if(x1 < rect_x) + { + if(x2 < rect_x) + return QLine(); + x1 = rect_x; + } + else + if(x1 > rect_right) + { + if(x2 > rect_right) + return QLine(); + x1 = rect_right; + } + + if(x2 < rect_x) + x2 = rect_x; + else + if(x2 > rect_right) + x2 = rect_right; + + if(y1 < rect_y) + { + if(y2 < rect_y) + return QLine(); + y1 = rect_y; + } + else + if(y1 > rect_bot) + { + if(y2 > rect_bot) + return QLine(); + y1 = rect_bot; + } + + if(y2 < rect_y) + y2 = rect_y; + if(y2 > rect_bot) + y2 = rect_bot; + + return QLine(x1, y1, x2, y2); +} } // namespace MusEGui diff --git a/muse2/muse/helper.h b/muse2/muse/helper.h index 0eab7ee2..56bd0bc8 100644 --- a/muse2/muse/helper.h +++ b/muse2/muse/helper.h @@ -33,7 +33,8 @@ class QActionGroup; class QString; class QMenu; class QWidget; - +class QLine; +class QRect; namespace MusECore { class Part; @@ -76,6 +77,7 @@ QString projectExtensionFromFilename(QString filename); QString getUniqueUntitledName(); void populateMidiPorts(); int populateMidiCtrlMenu(PopupMenu* menu, MusECore::PartList* part_list, MusECore::Part* cur_part, int curDrumPitch); +QLine clipQLine(int x1, int y1, int x2, int y2, const QRect& rect); } #endif diff --git a/muse2/muse/waveedit/wavecanvas.cpp b/muse2/muse/waveedit/wavecanvas.cpp index 80341554..c27f6cef 100644 --- a/muse2/muse/waveedit/wavecanvas.cpp +++ b/muse2/muse/waveedit/wavecanvas.cpp @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include @@ -69,6 +71,7 @@ #include "utils.h" #include "tools.h" #include "copy_on_write.h" +#include "helper.h" namespace MusEGui { @@ -1032,14 +1035,14 @@ void WaveCanvas::drawItem(QPainter& p, const MusEGui::CItem* item, const QRect& return; int x1 = mr.x(); - int x2 = mr.right() + 1; + int x2 = x1 + mr.width(); if (x1 < 0) x1 = 0; if (x2 > width()) x2 = width(); int hh = height(); - int h = hh/2; - int y = mr.y() + h; + int y1 = mr.y(); + int y2 = y1 + mr.height(); int xScale = xmag; if (xScale < 0) @@ -1065,10 +1068,6 @@ void WaveCanvas::drawItem(QPainter& p, const MusEGui::CItem* item, const QRect& int pos = (xpos + sx) * xScale + event.spos() - event.frame() - px; - //printf("pos=%d xpos=%d sx=%d ex=%d xScale=%d event.spos=%d event.frame=%d px=%d\n", - // pos, xpos, sx, ex, xScale, event.spos(), event.frame(), px); - - QBrush brush; if (item->isMoving()) { @@ -1078,7 +1077,7 @@ void WaveCanvas::drawItem(QPainter& p, const MusEGui::CItem* item, const QRect& gradient.setColorAt(0, c); gradient.setColorAt(1, c.darker()); brush = QBrush(gradient); - p.fillRect(sx, 0, ex - sx, hh, brush); + p.fillRect(sx, y1, ex - sx + 1, y2, brush); } else if (item->isSelected()) @@ -1088,94 +1087,142 @@ void WaveCanvas::drawItem(QPainter& p, const MusEGui::CItem* item, const QRect& QLinearGradient gradient(r.topLeft(), r.bottomLeft()); // Use a colour only about 20% lighter than black, rather than the 50% we use in MusECore::gGradientFromQColor // and is used in darker()/lighter(), so that it is distinguished a bit better from grey non-part tracks. - //c.setRgba(64, 64, 64, c.alpha()); gradient.setColorAt(0, QColor(51, 51, 51, MusEGlobal::config.globalAlphaBlend)); gradient.setColorAt(1, c); brush = QBrush(gradient); - p.fillRect(sx, 0, ex - sx, hh, brush); - } - //else - { - QPen pen(Qt::DashLine); - pen.setColor(Qt::black); - pen.setCosmetic(true); - p.setPen(pen); - p.drawRect(sx, 0, ex - sx, hh); - } - //p.fillRect(sx, 0, ex - sx, hh, brush); - //p.drawRect(sx, 0, ex - sx, hh, brush); - - MusECore::SndFileR f = event.sndFile(); - if(f.isNull()) - { - p.setWorldMatrixEnabled(wmtxen); - return; + p.fillRect(sx, y1, ex - sx + 1, y2, brush); } - - int ev_channels = f.channels(); - if (ev_channels == 0) { - p.setWorldMatrixEnabled(wmtxen); - printf("WaveCnvas::drawItem: ev_channels==0! %s\n", f.name().toLatin1().constData()); - return; - } - - h = hh / (ev_channels * 2); - int cc = hh % (ev_channels * 2) ? 0 : 1; - unsigned peoffset = px + event.frame() - event.spos(); - - for (int i = sx; i < ex; i++) { - y = mr.y() + h; - MusECore::SampleV sa[f.channels()]; - f.read(sa, xScale, pos); - pos += xScale; - if (pos < event.spos()) - continue; + MusECore::SndFileR f = event.sndFile(); + if(!f.isNull()) + { + int ev_channels = f.channels(); + if (ev_channels == 0) { + p.setWorldMatrixEnabled(wmtxen); + printf("WaveCnvas::drawItem: ev_channels==0! %s\n", f.name().toLatin1().constData()); + return; + } - int selectionStartPos = selectionStart - peoffset; // Offset transformed to event coords - int selectionStopPos = selectionStop - peoffset; - - for (int k = 0; k < ev_channels; ++k) { - int kk = k % f.channels(); - int peak = (sa[kk].peak * (h - 1)) / yScale; - int rms = (sa[kk].rms * (h - 1)) / yScale; - if (peak > h) - peak = h; - if (rms > h) - rms = h; - QColor peak_color = QColor(Qt::darkGray); - QColor rms_color = QColor(Qt::black); - - // Changed by T356. Reduces (but not eliminates) drawing artifacts. (TODO Cause of artifacts gone, correct this now.) - //if (pos > selectionStartPos && pos < selectionStopPos) { - if (pos > selectionStartPos && pos <= selectionStopPos) { - - peak_color = QColor(Qt::lightGray); - rms_color = QColor(Qt::white); - // Draw inverted - p.setPen(QColor(Qt::black)); - p.drawLine(i, y - h + cc, i, y + h - cc ); + int h = hh / (ev_channels * 2); + int cc = hh % (ev_channels * 2) ? 0 : 1; + + unsigned peoffset = px + event.frame() - event.spos(); + + for (int i = sx; i < ex; i++) { + int y = h; + MusECore::SampleV sa[f.channels()]; + f.read(sa, xScale, pos); + pos += xScale; + if (pos < event.spos()) + continue; + + int selectionStartPos = selectionStart - peoffset; // Offset transformed to event coords + int selectionStopPos = selectionStop - peoffset; + + for (int k = 0; k < ev_channels; ++k) { + int kk = k % f.channels(); + int peak = (sa[kk].peak * (h - 1)) / yScale; + int rms = (sa[kk].rms * (h - 1)) / yScale; + if (peak > h) + peak = h; + if (rms > h) + rms = h; + QColor peak_color = QColor(Qt::darkGray); + QColor rms_color = QColor(Qt::black); + + if (pos > selectionStartPos && pos < selectionStopPos) { + peak_color = QColor(Qt::lightGray); + rms_color = QColor(Qt::white); + QLine l_inv = clipQLine(i, y - h + cc, i, y + h - cc, mr); + if(!l_inv.isNull()) + { + // Draw inverted + p.setPen(QColor(Qt::black)); + p.drawLine(l_inv); + } } - p.setPen(peak_color); - p.drawLine(i, y - peak - cc, i, y + peak); - p.setPen(rms_color); - p.drawLine(i, y - rms - cc, i, y + rms); - y += 2 * h; + + QLine l_peak = clipQLine(i, y - peak - cc, i, y + peak, mr); + if(!l_peak.isNull()) + { + p.setPen(peak_color); + p.drawLine(l_peak); + } + + QLine l_rms = clipQLine(i, y - rms - cc, i, y + rms, mr); + if(!l_rms.isNull()) + { + p.setPen(rms_color); + p.drawLine(l_rms); + } + + y += 2 * h; } - } + } - - int hn = hh / ev_channels; - int hhn = hn / 2; - for (int i = 0; i < ev_channels; ++i) { - int h2 = hn * i; - int center = hhn + h2; - p.setPen(QColor(i & i ? Qt::red : Qt::blue)); - p.drawLine(sx, center, ex, center); - p.setPen(QColor(Qt::black)); - p.drawLine(sx, h2, ex, h2); + int hn = hh / ev_channels; + int hhn = hn / 2; + for (int i = 0; i < ev_channels; ++i) { + int h2 = hn * i; + int center = hhn + h2; + if(center >= y1 && center < y2) + { + p.setPen(QColor(i & 1 ? Qt::red : Qt::blue)); + p.drawLine(sx, center, ex, center); + } + if(i != 0 && h2 >= y1 && h2 < y2) + { + p.setPen(QColor(Qt::black)); + p.drawLine(sx, h2, ex, h2); + } } - + } + + // + // Draw custom dashed borders around the wave event + // + + QColor color(item->isSelected() ? Qt::white : Qt::black); + QPen penH(color); + QPen penV(color); + penH.setCosmetic(true); + penV.setCosmetic(true); + QVector customDashPattern; + customDashPattern << 4.0 << 6.0; + penH.setDashPattern(customDashPattern); + penV.setDashPattern(customDashPattern); + penV.setDashOffset(2.0); + // FIXME: Some shifting still going on. Values likely not quite right here. + //int xdiff = sx - r.x(); + int xdiff = sx - mer.x(); + if(xdiff > 0) + { + int doff = xdiff % 10; + penH.setDashOffset(doff); + } + // Tested OK. Each segment drawn only when necessary. + if(y1 <= 0) + { + p.setPen(penH); + p.drawLine(sx, 0, ex, 0); + } + if(y2 >= hh - 1) + { + p.setPen(penH); + p.drawLine(sx, hh - 1, ex, hh - 1); + } + if(x1 <= mer.x()) + { + p.setPen(penV); + p.drawLine(mer.x(), y1, mer.x(), y2); + } + if(x2 >= mer.x() + mer.width()) + { + p.setPen(penV); + p.drawLine(mer.x() + mer.width(), y1, mer.x() + mer.width(), y2); + } + + // Done. Restore and return. p.setWorldMatrixEnabled(wmtxen); } diff --git a/muse2/muse/widgets/canvas.cpp b/muse2/muse/widgets/canvas.cpp index b5df2494..51612884 100644 --- a/muse2/muse/widgets/canvas.cpp +++ b/muse2/muse/widgets/canvas.cpp @@ -730,26 +730,26 @@ void Canvas::viewMousePressEvent(QMouseEvent* event) case PanTool: { drag = DRAG_PAN; + setCursor(); if(MusEGlobal::config.borderlessMouse) { QRect r = QApplication::desktop()->screenGeometry(); ignore_mouse_move = true; // Avoid recursion. QCursor::setPos( QPoint(r.width()/2, r.height()/2) ); } - setCursor(); } break; case ZoomTool: { drag = DRAG_ZOOM; + setCursor(); if(MusEGlobal::config.borderlessMouse) { QRect r = QApplication::desktop()->screenGeometry(); ignore_mouse_move = true; // Avoid recursion. QCursor::setPos( QPoint(r.width()/2, r.height()/2) ); } - setCursor(); // Update the small zoom drawing area QPoint pt = mapFromGlobal(global_start); update(pt.x(), pt.y(), zoomIcon->width(), zoomIcon->height()); -- cgit v1.2.3