From 96cd2ef23505deaadb030ea0f1ef284e8a753452 Mon Sep 17 00:00:00 2001 From: "Tim E. Real" Date: Tue, 16 Aug 2011 07:40:48 +0000 Subject: More drawing fixes, improved accuracy (grids, timescales, edges, markers guaranteed to align now). Much drawing changed to device (pixel) space instead of virtual space, for accuracy. Fixed display of audio automation graphs. (But not editing). --- muse2/muse/arranger/pcanvas.cpp | 457 ++++++++++++++++++++++++++-------------- 1 file changed, 295 insertions(+), 162 deletions(-) (limited to 'muse2/muse/arranger/pcanvas.cpp') diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index 402e8035..82f2de45 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -70,17 +70,9 @@ NPart::NPart(Part* e) : CItem(Event(), e) leftBorderTouches = false; rightBorderTouches = false; - int th = track()->height(); int y = track()->y(); - - ///setPos(QPoint(e->tick(), y + 1)); setPos(QPoint(e->tick(), y)); - - ///setBBox(QRect(e->tick(), y + 1, e->lenTick(), th)); - // NOTE: For adjustable border size: If using a two-pixel border width while drawing, use second line. - // If one-pixel width, use first line. Tim. - //setBBox(QRect(e->tick(), y, e->lenTick(), th)); - setBBox(QRect(e->tick(), y + 1, e->lenTick(), th)); + setBBox(QRect(e->tick(), y, e->lenTick(), track()->height())); } //--------------------------------------------------------- @@ -1727,22 +1719,24 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) if((unsigned int)to > part->lenTick()) to = part->lenTick(); + bool clone = part->events()->arefCount() > 1; + QBrush brush; + + QRect r = item->bbox(); + // Compensation required for two pixel wide border. FIXME Prefer to do this after the map, but r is needed below. + r.moveTop(r.y() + rmapyDev(1)); + //QRect rr = p.transform().mapRect(r); // Gives inconsistent positions. Source shows wrong operation for our needs. + QRect rr = map(r); // Use our own map instead. + // Item bounding box x is in tick coordinates, same as rectangle. - if(item->bbox().intersect(rect).isNull()) + //if(item->bbox().intersect(rect).isNull()) + //if((item->bbox() & rect).isNull()) + if((rr & map(rect)).isNull()) { //printf("PartCanvas::drawItem rectangle is null\n"); return; } - QRect r = item->bbox(); - bool clone = part->events()->arefCount() > 1; - QBrush brush; - - //QRect rr = map(r); // Produced inconsistent positions. FIXME - //QRect rr = p.transform().mapRect(r); // Same. - QRect rr(QPoint(mapx(r.x()), mapy(r.y())), - QPoint(mapx(r.x() + r.width()) - 1, mapy(r.y() + r.height() - 1))); // Test OK so far. - //printf("PartCanvas::drawItem called map rx:%d rw:%d rrx:%d rrw:%d\n", r.x(), r.width(), rr.x(), rr.width()); //printf("PartCanvas::drawItem called map rx:%d rw:%d\n", r.x(), r.width()); @@ -1762,9 +1756,9 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) int xs_2 = xs_0 + 2; if(xs_2 > xe_0) xs_2 = xe_0; - int xs_6 = xs_0 + 6; - if(xs_6 > xe_0) - xs_6 = xe_0; + int xs_j = xs_0 + 8; + if(xs_j > xe_0) + xs_j = xe_0; int xe_1 = xe_0 - 1; if(xe_1 < xs_0) @@ -1772,11 +1766,11 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) int xe_2 = xe_0 - 2; if(xe_2 < xs_0) xe_2 = xs_0; - int xe_6 = xe_0 - 6; - if(xe_6 < xs_0) - xe_6 = xs_0; + int xe_j = xe_0 - 8; + if(xe_j < xs_0) + xe_j = xs_0; - int ys_0 = rr.y(); + int ys_0 = rr.y(); int ye_0 = ys_0 + rr.height(); int ys_1 = ys_0 + 1; if(ys_1 > ye_0) @@ -1784,6 +1778,9 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) int ys_2 = ys_0 + 2; if(ys_2 > ye_0) ys_2 = ye_0; + int ys_3 = ys_0 + 3; + if(ys_3 > ye_0) + ys_3 = ye_0; int ye_1 = ye_0 - 1; if(ye_1 < ys_0) @@ -1834,13 +1831,14 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) int h = rr.height(); double s = double(h) / 4.0; - int y0 = rr.y(); - int y1 = y0 + lrint(s); + int y0 = ys_0; + //int y1 = y0 + lrint(s); int y2 = y0 + lrint(s * 2.0); - int y3 = y0 + lrint(s * 3.0); + //int y3 = y0 + lrint(s * 3.0); int y4 = y0 + h; - QPoint points[16]; + //QPoint points[12]; + QPoint points[8]; int pts; // @@ -1854,41 +1852,62 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) pts = 0; if(het == (Part::LeftEventsHidden | Part::RightEventsHidden)) { + //points[pts++] = QPoint(xs_0, y0); + //points[pts++] = QPoint(xe_0, y0); + //points[pts++] = QPoint(xe_j, y1); + //points[pts++] = QPoint(xe_0, y2); + //points[pts++] = QPoint(xe_j, y3); + //points[pts++] = QPoint(xe_0, y4); + //points[pts++] = QPoint(xs_0, y4); + //points[pts++] = QPoint(xs_j, y3); + //points[pts++] = QPoint(xs_0, y2); + //points[pts++] = QPoint(xs_j, y1); + points[pts++] = QPoint(xs_0, y0); points[pts++] = QPoint(xe_0, y0); - points[pts++] = QPoint(xe_6, y1); - points[pts++] = QPoint(xe_0, y2); - points[pts++] = QPoint(xe_6, y3); + points[pts++] = QPoint(xe_j, y2); points[pts++] = QPoint(xe_0, y4); points[pts++] = QPoint(xs_0, y4); - points[pts++] = QPoint(xs_6, y3); - points[pts++] = QPoint(xs_0, y2); - points[pts++] = QPoint(xs_6, y1); + points[pts++] = QPoint(xs_j, y2); + p.drawConvexPolygon(points, pts); // Help says may be faster on some platforms (X11). } else if(het == Part::LeftEventsHidden) { + //points[pts++] = QPoint(xs_0, y0); + //points[pts++] = QPoint(xe_0, y0); + //points[pts++] = QPoint(xe_0, y4); + //points[pts++] = QPoint(xs_0, y4); + //points[pts++] = QPoint(xs_j, y3); + //points[pts++] = QPoint(xs_0, y2); + //points[pts++] = QPoint(xs_j, y1); + points[pts++] = QPoint(xs_0, y0); points[pts++] = QPoint(xe_0, y0); points[pts++] = QPoint(xe_0, y4); points[pts++] = QPoint(xs_0, y4); - points[pts++] = QPoint(xs_6, y3); - points[pts++] = QPoint(xs_0, y2); - points[pts++] = QPoint(xs_6, y1); + points[pts++] = QPoint(xs_j, y2); + p.drawConvexPolygon(points, pts); } else if(het == Part::RightEventsHidden) { + //points[pts++] = QPoint(xs_0, y0); + //points[pts++] = QPoint(xe_0, y0); + //points[pts++] = QPoint(xe_j, y1); + //points[pts++] = QPoint(xe_0, y2); + //points[pts++] = QPoint(xe_j, y3); + //points[pts++] = QPoint(xe_0, y4); + //points[pts++] = QPoint(xs_0, y4); + points[pts++] = QPoint(xs_0, y0); points[pts++] = QPoint(xe_0, y0); - - points[pts++] = QPoint(xe_6, y1); - points[pts++] = QPoint(xe_0, y2); - points[pts++] = QPoint(xe_6, y3); + points[pts++] = QPoint(xe_j, y2); points[pts++] = QPoint(xe_0, y4); points[pts++] = QPoint(xs_0, y4); + p.drawConvexPolygon(points, pts); } @@ -1904,30 +1923,40 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) //else // color_brightness=32; // otherwise use dark color if ((brightness >= 12000 && !part->selected())) - color_brightness=32; // too light: use dark color + color_brightness=96; //0; // too light: use dark color else - color_brightness=223; // too dark: use lighter color + color_brightness=180; //255; // too dark: use lighter color QColor c(color_brightness,color_brightness,color_brightness, config.globalAlphaBlend); p.setBrush(QBrush(gGradientFromQColor(c, rr.topLeft(), rr.bottomLeft()))); //p.setBrush(QBrush(c)); if(het & Part::RightEventsHidden) { pts = 0; + //points[pts++] = QPoint(xe_0, y0); + //points[pts++] = QPoint(xe_0, y4); + //points[pts++] = QPoint(xe_j, y3); + //points[pts++] = QPoint(xe_0, y2); + //points[pts++] = QPoint(xe_j, y1); + points[pts++] = QPoint(xe_0, y0); points[pts++] = QPoint(xe_0, y4); - points[pts++] = QPoint(xe_6, y3); - points[pts++] = QPoint(xe_0, y2); - points[pts++] = QPoint(xe_6, y1); + points[pts++] = QPoint(xe_j, y2); + p.drawConvexPolygon(points, pts); } if(het & Part::LeftEventsHidden) { pts = 0; + //points[pts++] = QPoint(xs_0, y0); + //points[pts++] = QPoint(xs_j, y1); + //points[pts++] = QPoint(xs_0, y2); + //points[pts++] = QPoint(xs_j, y3); + //points[pts++] = QPoint(xs_0, y4); + points[pts++] = QPoint(xs_0, y0); - points[pts++] = QPoint(xs_6, y1); - points[pts++] = QPoint(xs_0, y2); - points[pts++] = QPoint(xs_6, y3); + points[pts++] = QPoint(xs_j, y2); points[pts++] = QPoint(xs_0, y4); + p.drawConvexPolygon(points, pts); } } @@ -1985,14 +2014,6 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) // Now draw the borders, using custom segments... // - // FIXME NOTE: For 1-pixel wide lines, setting pen style to anything other than solid didn't work out well. - // Much too screwy - the single-width lines kept getting shifted one pixel over intermittently. - // I tried EVERYTHING to make sure x is proper but the painter keeps shifting them over. - // Meanwhile the fills are correct. Seems painter doesn't like line patterns, whether stock or custom. - // Therefore I was forced to manually draw the left and right segments. - // It works. Which seems to be more proof that painter is handling line patterns and pen widths badly... - // DO NOT ERASE COMMENTED CODE BELOW for now, in case it can be fixed. Tim. p4.0.29 - p.setBrush(Qt::NoBrush); QColor pc((part->mute() || item->isMoving())? Qt::white : config.partColors[cidx]); @@ -2015,52 +2036,57 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) penNormal1V.setCosmetic(true); penNormal2V.setCosmetic(true); + //pc = Qt::white; + //pc = Qt::darkGray; + //QPen penHidden1(pc); + //QPen penHidden2(pc, 2.0); + //penHidden2.setCosmetic(true); + QVector customDashPattern; + if(clone) { - customDashPattern << 4.0 << 8.0; + customDashPattern << 4.0 << 6.0; penSelect1H.setDashPattern(customDashPattern); penNormal1H.setDashPattern(customDashPattern); - //penSelect1V.setDashPattern(customDashPattern); - //penNormal1V.setDashPattern(customDashPattern); + penSelect1V.setDashPattern(customDashPattern); + penNormal1V.setDashPattern(customDashPattern); + penSelect1V.setDashOffset(2.0); + penNormal1V.setDashOffset(2.0); + //penHidden1.setDashPattern(customDashPattern); customDashPattern.clear(); - customDashPattern << 2.0 << 4.0; + customDashPattern << 2.0 << 3.0; penSelect2H.setDashPattern(customDashPattern); penNormal2H.setDashPattern(customDashPattern); - //penSelect2V.setDashPattern(customDashPattern); - //penNormal2V.setDashPattern(customDashPattern); + penSelect2V.setDashPattern(customDashPattern); + penNormal2V.setDashPattern(customDashPattern); + penSelect2V.setDashOffset(1.0); + penNormal2V.setDashOffset(1.0); + //penHidden2.setDashPattern(customDashPattern); } - pc = Qt::white; - QPen penHidden1(pc); - QPen penHidden2(pc, 2.0); - penHidden2.setCosmetic(true); - //customDashPattern.clear(); - //customDashPattern << 2.0 << 10.0; - //penHidden1.setDashPattern(customDashPattern); - //customDashPattern.clear(); - //customDashPattern << 1.0 << 5.0; - //penHidden2.setDashPattern(customDashPattern); - bool lbt = ((NPart*)item)->leftBorderTouches; bool rbt = ((NPart*)item)->rightBorderTouches; - QLine l1( lbt?xs_1:xs_0, ys_0, rbt?xe_1:xe_0, ys_0); // Top - //QLine l2(rbt?xe_1:xe_0, r.y() + (rbt?y_1:y_2) - 1, rbt?xe_1:xe_0, r.y() + r.height() - 1); // Right - QLine l3( lbt?xs_1:xs_0, ye_0, rbt?xe_1:xe_0, ye_0); // Bottom - //QLine l4(r.x(), r.y() + (lbt?y_1:y_2), r.x(), r.y() + r.height() - (lbt?y_1:y_2)); // Left + QLine l1(lbt?xs_1:xs_0, ys_0, rbt?xe_1:xe_0, ys_0); // Top + //QLine l2(rbt?xe_1:xe_0, rbt?ys_1:ys_2, rbt?xe_1:xe_0, rbt?ye_1:ye_2); // Right + QLine l2(rbt?xe_1:xe_0, ys_0, rbt?xe_1:xe_0, ye_0); // Right + QLine l3(lbt?xs_1:xs_0, ye_0, rbt?xe_1:xe_0, ye_0); // Bottom + //QLine l4(xs_0, lbt?ys_1:ys_2, xs_0, lbt?ye_1:ye_2); // Left + QLine l4(xs_0, ys_0, xs_0, ye_0); // Left - if(het & Part::RightEventsHidden) - p.setPen(((NPart*)item)->rightBorderTouches ? penHidden1 : penHidden2); - else + //if(het & Part::RightEventsHidden) + // p.setPen(((NPart*)item)->rightBorderTouches ? penHidden1 : penHidden2); + //else { if(((NPart*)item)->rightBorderTouches) p.setPen(part->selected() ? penSelect1V : penNormal1V); else p.setPen(part->selected() ? penSelect2V : penNormal2V); } - //p.drawLine(l2); // Right line + p.drawLine(l2); // Right line + /* int xx = rbt?xe_1:xe_0; if(clone) { @@ -2075,18 +2101,20 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) } else p.drawLine(QPoint(xx, rbt?ys_1:ys_2), QPoint(xx, rbt?ye_1:ye_2)); // Right line + */ - if(het & Part::LeftEventsHidden) - p.setPen(((NPart*)item)->leftBorderTouches ? penHidden1 : penHidden2); - else + //if(het & Part::LeftEventsHidden) + // p.setPen(((NPart*)item)->leftBorderTouches ? penHidden1 : penHidden2); + //else { if(((NPart*)item)->leftBorderTouches) p.setPen(part->selected() ? penSelect1V : penNormal1V); else p.setPen(part->selected() ? penSelect2V : penNormal2V); } - //p.drawLine(l4); // Left line + p.drawLine(l4); // Left line + /* xx = xs_0; if(clone) { @@ -2101,6 +2129,7 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) } else p.drawLine(QPoint(xx, lbt?ys_1:ys_2), QPoint(xx, lbt?ye_1:ye_2)); // Left line + */ p.setPen(part->selected() ? penSelect2H : penNormal2H); p.drawLine(l1); // Top line @@ -2133,8 +2162,9 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) p.setPen(Qt::white); p.drawText(tr, Qt::AlignBottom|Qt::AlignLeft, part->name()); } + p.restore(); - p.setWorldMatrixEnabled(true); + //p.setWorldMatrixEnabled(true); } //--------------------------------------------------------- @@ -2174,9 +2204,9 @@ void PartCanvas::drawMidiPart(QPainter& p, const QRect&, EventList* events, Midi //else // color_brightness=64; // otherwise use dark color if (brightness >= 12000 && !pt->selected()) - color_brightness=64; // too bright: use dark color + color_brightness=64; // 96; // too bright: use dark color else - color_brightness=192; // too dark: use lighter color + color_brightness=190; //160; // too dark: use lighter color } else color_brightness=80; @@ -2392,8 +2422,10 @@ void PartCanvas::drawMidiPart(QPainter& p, const QRect&, EventList* events, Midi void PartCanvas::drawWavePart(QPainter& p, const QRect& bb, WavePart* wp, const QRect& _pr) { - QRect rr = p.worldMatrix().mapRect(bb); - QRect pr = p.worldMatrix().mapRect(_pr); + //QRect rr = p.worldMatrix().mapRect(bb); // Gives inconsistent positions. Source shows wrong operation for our needs. + QRect rr = map(bb); // Use our own map instead. + //QRect pr = p.worldMatrix().mapRect(_pr); + QRect pr = map(_pr); p.save(); p.resetTransform(); @@ -3066,9 +3098,22 @@ void PartCanvas::viewDropEvent(QDropEvent* event) void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) { int x = rect.x(); - int y = rect.y(); + //int y = rect.y(); int w = rect.width(); - int h = rect.height(); + //int h = rect.height(); + + // Changed to draw in device coordinate space instead of virtual, transformed space. Tim. p4.0.30 + + //QRect mr = p.transform().mapRect(rect); // Gives inconsistent positions. Source shows wrong operation for our needs. + QRect mr = map(rect); // Use our own map instead. + + p.save(); + p.setWorldMatrixEnabled(false); + + int mx = mr.x(); + int my = mr.y(); + int mw = mr.width(); + int mh = mr.height(); ////////// // GRID // @@ -3086,13 +3131,17 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) AL::sigmap.tickValues(x, &bar, &beat, &tick); for (;;) { int xt = AL::sigmap.bar2tick(bar++, 0, 0); + //int xt = mapx(AL::sigmap.bar2tick(bar++, 0, 0)); if (xt >= x + w) + //if (xt >= mx + mw) break; if (!((bar-1) % 4)) p.setPen(baseColor.dark(115)); else p.setPen(baseColor); - p.drawLine(xt, y, xt, y+h); + //p.drawLine(xt, y, xt, y+h); + int xtm = mapx(xt); + p.drawLine(xtm, my, xtm, my+mh); // append int noDivisors=0; @@ -3118,20 +3167,28 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) noDivisors=noDivisors/2; } p.setPen(baseColor); + int xx; for (int t=1;t< noDivisors;t++) - p.drawLine(xt+r*t, y, xt+r*t, y+h); + { + //p.drawLine(xt+r*t, y, xt+r*t, y+h); + xx = mapx(xt + r * t); + p.drawLine(xx, my, xx, my+mh); + } } } } + //-------------------------------- // horizontal lines //-------------------------------- TrackList* tl = song->tracks(); - int yy = 0; + //int yy = 0; + int yy = -rmapy(yorg) - ypos; int th; for (iTrack it = tl->begin(); it != tl->end(); ++it) { - if (yy > y + h) + //if (yy > y + h) + if (yy > my + mh) break; Track* track = *it; th = track->height(); @@ -3140,22 +3197,46 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) if (config.canvasShowGrid && (track->isMidiTrack() || track->type() == Track::WAVE)) // Tim. { p.setPen(baseColor.dark(130)); - p.drawLine(x, yy + th, x + w, yy + th); // Tim. - p.setPen(baseColor); - } - if (!track->isMidiTrack() && (track->type() != Track::WAVE)) { - QRect r = rect & QRect(x, yy, w, track->height()); - drawAudioTrack(p, r, (AudioTrack*)track); - p.setPen(baseColor); + //p.drawLine(x, yy + th, x + w, yy + th); + p.drawLine(mx, yy + th, mx + mw, yy + th); + //p.setPen(baseColor); } - if (!track->isMidiTrack()) { // draw automation - QRect r = rect & QRect(x, yy, w, track->height()); - drawAutomation(p, r, (AudioTrack*)track); - p.setPen(baseColor); - - } - yy += track->height(); + + // The update rectangle (rect and mr etc) is clipped at x<0 and y<0 in View::pdraw(). + // The 'corrupt drawing' bug of drawAudioTrack was actually because the recently added gradient + // used the update rectangle, so the gradient was also being clipped at 0,0. + // One could remove that limiter, but no, that is the correct way. So instead let's construct a + // 'pseudo bounding box' (half update rectangle, half bounding box), un-clipped. The gradient needs this! + // + // Here is a different situation than PartCanvas::drawItem which uses un-clipped part bounding boxes and + // does NOT depend on the update rectangle (except to check intersection). That's why this issue + // does not show up there. Should probably try to make that routine more efficient, just like here. Tim. p4.0.30 + QRect r(mx, yy, mw, th); + //if(r.intersects(mr)) + { + if (!track->isMidiTrack() && (track->type() != Track::WAVE)) { + //QRect r = rect & QRect(x, yy, w, track->height()); + drawAudioTrack(p, mr, r, (AudioTrack*)track); + //p.setPen(baseColor); + } + + // This was redundant drawing. Not required, done via drawTopItem in Canvas::draw + /* + //p.setWorldMatrixEnabled(true); + //if (!track->isMidiTrack()) { // draw automation + if (!track->isMidiTrack() && (track->type() != Track::WAVE)) { + //QRect r = rect & QRect(x, yy, w, track->height()); + drawAutomation(p, r, (AudioTrack*)track); + //p.setPen(baseColor); + } + //p.setWorldMatrixEnabled(false); + */ } + yy += th; + } + + p.restore(); + //p.setWorldMatrixEnabled(true); } //--------------------------------------------------------- @@ -3163,36 +3244,55 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) //--------------------------------------------------------- void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) { - int x = rect.x(); - int y = rect.y(); - int w = rect.width(); - int h = rect.height(); + //int x = rect.x(); + //int y = rect.y(); + //int w = rect.width(); + //int h = rect.height(); + // Changed to draw in device coordinate space instead of virtual, transformed space. Tim. p4.0.30 + + //QRect mr = p.transform().mapRect(rect); // Gives inconsistent positions. Source shows wrong operation for our needs. + QRect mr = map(rect); // Use our own map instead. + + //printf("PartCanvas::drawTopItem x:%d y:%d w:%d h:%d\n", rect.x(), rect.y(), rect.width(), rect.height()); + + int mx = mr.x(); + int my = mr.y(); + int mw = mr.width(); + int mh = mr.height(); + QColor baseColor(config.partCanvasBg.light(104)); - p.setPen(baseColor); + //p.setPen(baseColor); + p.save(); + p.setWorldMatrixEnabled(false); + TrackList* tl = song->tracks(); - int yy = 0; + int yoff = -rmapy(yorg) - ypos; + //int yy = 0; + int yy = yoff; int th; for (iTrack it = tl->begin(); it != tl->end(); ++it) { - if (yy > y + h) + //if (yy > y + h) + if (yy > my + mh) break; Track* track = *it; th = track->height(); if (!th) continue; if (!track->isMidiTrack()) { // draw automation - QRect r = rect & QRect(x, yy, w, track->height()); - drawAutomation(p, r, (AudioTrack*)track); - p.setPen(baseColor); - + //QRect r = rect & QRect(x, yy, w, track->height()); + QRect r(mx, yy, mw, th); + if(r.intersects(mr)) + { + drawAutomation(p, r, (AudioTrack*)track); + //p.setPen(baseColor); + } } - yy += track->height(); + //yy += track->height(); + yy += th; } - QRect rr = p.worldMatrix().mapRect(rect); - - unsigned int startPos = audio->getStartRecordPos().tick(); if (song->punchin()) startPos=song->lpos(); @@ -3200,38 +3300,47 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) int width = mapx(song->cpos()) - mapx(startPos); if (song->cpos() < startPos) { + //p.setWorldMatrixEnabled(true); + p.restore(); return; // no drawing if we are before punch out } if (song->punchout() && song->cpos() > song->rpos()) { + //p.setWorldMatrixEnabled(true); + p.restore(); return; // no drawing if we are beyond punch out. } - p.save(); - p.resetTransform(); + ///p.save(); + ///p.resetTransform(); // write recording while it happens to get feedback // should be enhanced with solution that draws waveform also - int yPos=0; + //int yPos=0; + int yPos = yoff; if (song->record() && audio->isPlaying()) { for (iTrack it = tl->begin(); it != tl->end(); ++it) { Track* track = *it; + th = track->height(); + if (!th) + continue; if (track->recordFlag()) { QPen pen(Qt::black, 0, Qt::SolidLine); p.setPen(pen); QColor c(config.partColors[0]); c.setAlpha(config.globalAlphaBlend); - QLinearGradient gradient(QPoint(startx,yPos), QPoint(startx,yPos+track->height())); + QLinearGradient gradient(QPoint(startx,yPos), QPoint(startx,yPos+th)); gradient.setColorAt(0, c); gradient.setColorAt(1, c.darker()); QBrush cc(gradient); p.setBrush(cc); - p.drawRect(startx,yPos, width, track->height()); + p.drawRect(startx,yPos, width, th); } - yPos+=track->height(); + yPos+=th; } } p.restore(); + //p.setWorldMatrixEnabled(true); // draw midi events on yPos=0; @@ -3275,53 +3384,71 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) } } - } //--------------------------------------------------------- // drawAudioTrack //--------------------------------------------------------- -void PartCanvas::drawAudioTrack(QPainter& p, const QRect& r, AudioTrack* /* t */) +void PartCanvas::drawAudioTrack(QPainter& p, const QRect& r, const QRect& bbox, AudioTrack* /*t*/) { - // NOTE: For one-pixel border use first line and don't bother with setCosmetic. - // For a two-pixel border use second line and MUST use setCosmetic! Tim. - QPen pen(Qt::black, 0, Qt::SolidLine); - //p.setPen(QPen(Qt::black, 2, Qt::SolidLine)); - //pen.setCosmetic(true); - p.setPen(pen); - //p.setBrush(Qt::gray); - + QRect mr = r & bbox; + if(mr.isNull()) + return; + int mx = mr.x(); + int my = mr.y(); + int mw = mr.width(); + int mh = mr.height(); + int mex = bbox.x(); + int mey = bbox.y(); + //int mew = bbox.width(); + int meh = bbox.height(); + + p.setPen(Qt::black); QColor c(Qt::gray); c.setAlpha(config.globalAlphaBlend); - QLinearGradient gradient(r.topLeft(), r.bottomLeft()); + //QLinearGradient gradient(r.topLeft(), r.bottomLeft()); + QLinearGradient gradient(mex + 1, mey + 1, mex + 1, mey + meh - 1); // Inside the border gradient.setColorAt(0, c); gradient.setColorAt(1, c.darker()); - QBrush cc(gradient); - p.setBrush(cc); - p.drawRect(r); - - // Factor in pen stroking size: - //QRect rr(r); - //rr.setHeight(rr.height() -1); + QBrush brush(gradient); + p.fillRect(mr, brush); // p4.0.30 ... -// p.fillRect(r, cc); + //int xx = -rmapx(xorg) - xpos; + //printf("PartCanvas::drawAudioTrack x:%d y:%d w:%d h:%d th:%d xx:%d\n", r.x(), r.y(), r.width(), r.height(), t->height(), xx); + //if(r.x() <= xx) + // p.drawLine(r.x(), r.y(), r.x(), r.y() + r.height()); // The left edge + //p.drawLine(r.x(), r.y(), r.x() + r.width(), r.y()); // The top edge + //p.drawLine(r.x(), r.y() + r.height(), r.x() + r.width(), r.y() + r.height()); // The bottom edge + + if(mex >= mx && mex <= mx + mw) + p.drawLine(mex, my, mex, my + mh - 1); // The left edge + //if(mex + mew >= mx && mex + mew <= mx + mw) + // p.drawLine(mex + mew, my, mex + mew, my + mh - 1); // The right edge. Not used - infinite to the right + if(mey >= my && mey <= my + mh) + p.drawLine(mx, mey, mx + mw - 1, mey); // The top edge + if(mey + meh >= my && mey + meh <= my + mh) + p.drawLine(mx, mey + meh, mx + mw - 1, mey + meh); // The bottom edge. Special for Audio track - draw one past bottom. } //--------------------------------------------------------- // drawAutomation //--------------------------------------------------------- -void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) +void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, AudioTrack *t) { - QRect rr = p.worldMatrix().mapRect(r); + ///QRect rr = p.worldMatrix().mapRect(r); - p.save(); - p.resetTransform(); + ///p.save(); + ///p.resetTransform(); int height=rr.bottom()-rr.top()-4; // limit height + //printf("PartCanvas::drawAutomation x:%d y:%d w:%d h:%d height:%d\n", rr.x(), rr.y(), rr.width(), rr.height(), height); + + p.setBrush(Qt::NoBrush); + CtrlListList* cll = t->controller(); - bool firstRun=true; + ///bool firstRun=true; for(CtrlListList::iterator icll =cll->begin();icll!=cll->end();++icll) { //iCtrlList *icl = icll->second; @@ -3332,7 +3459,8 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) iCtrl ic=cl->begin(); if (!cl->isVisible()) continue; // skip this iteration if this controller isn't in the visible list - p.setPen(QPen(cl->color(),1,Qt::SolidLine)); + ///p.setPen(QPen(cl->color(),1,Qt::SolidLine)); + p.setPen(QPen(cl->color(), 0, Qt::SolidLine)); // First check that there ARE automation, ic == cl->end means no automation if (ic != cl->end()) { @@ -3358,6 +3486,7 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-2)-prevVal*height-1, 3, 3); p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5); + bool firstRun=true; for (; ic !=cl->end(); ++ic) { CtrlVal cv = ic->second; @@ -3378,6 +3507,7 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) } int currentPixel = mapx(tempomap.frame2tick(cv.frame)); + //printf(" line x1:%d x2:%d prevVal:%f nextVal:%f\n", leftX, currentPixel, prevVal, nextVal); p.drawLine( leftX, (rr.bottom()-2)-prevVal*height, currentPixel, @@ -3390,20 +3520,23 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) prevPosFrame=cv.frame; prevVal=nextVal; if (currentPixel > rr.x()+ rr.width()) - goto quitDrawing; + ///goto quitDrawing; + break; // draw a square around the point p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5); p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-1)-prevVal*height-2, 3, 3); } + //printf(" endline prevVal:%f\n", prevVal); p.drawLine(mapx(tempomap.frame2tick(prevPosFrame)), (rr.bottom()-2)-prevVal*height, rr.x()+rr.width(), (rr.bottom()-2)-prevVal*height); } } -quitDrawing: - p.restore(); +///quitDrawing: + ///p.restore(); + return; } -- cgit v1.2.3