SysStaff* System::insertStaff(int idx) { SysStaff* staff = new SysStaff; if (idx) { // HACK: guess position staff->bbox().setY(_staves[idx-1]->y() + 6 * spatium()); } _staves.insert(idx, staff); return staff; }
void ContinuousPanel::paint(const QRect&, QPainter& painter) { qreal _offsetPanel = 0; qreal _y = 0; qreal _oldWidth = 0; // The last final panel width qreal _newWidth = 0; // New panel width qreal _height = 0; qreal _leftMarginTotal = 0; // Sum of all elments left margin qreal _panelRightPadding = 5; // Extra space for the panel after last element Measure* measure = _score->firstMeasure(); if (!_active || !measure) { _visible = false; return; } if (measure->mmRest()) { measure = measure->mmRest(); } System* system = measure->system(); if (system == 0) { _visible = false; return; } Segment* s = measure->first(); double _spatium = _score->spatium(); if (_width <= 0) _width = s->x(); // // Set panel height for whole system // _height = 6 * _spatium; _y = system->staffYpage(0) + system->page()->pos().y(); double y2 = 0.0; for (int i = 0; i < _score->nstaves(); ++i) { SysStaff* ss = system->staff(i); if (!ss->show() || !_score->staff(i)->show()) continue; y2 = ss->y() + ss->bbox().height(); } _height += y2 + 6*_spatium; _y -= 6 * _spatium; // // Check elements at current panel position // _offsetPanel = -(_sv->xoffset()) / _sv->mag(); _rect = QRect(_offsetPanel + _width, _y, 1, _height); Page* page = _score->pages().front(); QList<Element*> el = page->items(_rect); if (el.empty()) { _visible = false; return; } qStableSort(el.begin(), el.end(), elementLessThan); const Measure*_currentMeasure = 0; for (const Element* e : el) { e->itemDiscovered = 0; if (!e->visible() && !_score->showInvisible()) continue; if (e->isMeasure()) { _currentMeasure = toMeasure(e); break; } } if (!_currentMeasure) return; // Don't show panel if staff names are visible if (_currentMeasure == _score->firstMeasure() && _sv->toPhysical(_currentMeasure->canvasPos()).x() > 0) { _visible = false; return; } qreal _xPosMeasure = _currentMeasure->canvasX(); qreal _measureWidth = _currentMeasure->width(); int tick = _currentMeasure->tick(); Fraction _currentTimeSig = _currentMeasure->timesig(); //qDebug() << "_sv->xoffset()=" <<_sv->xoffset() << " _sv->mag()="<< _sv->mag() <<" s->x=" << s->x() << " width=" << _width << " currentMeasure=" << _currentMeasure->x() << " _xPosMeasure=" << _xPosMeasure; //--------------------------------------------------------- // findElementWidths // determines the max width for each element types //--------------------------------------------------------- // The first pass serves to get the maximum width for each elements qreal lineWidthName = 0; qreal _widthClef = 0; qreal _widthKeySig = 0; qreal _widthTimeSig = 0; qreal _xPosTimeSig = 0; for (const Element* e : el) { e->itemDiscovered = 0; if (!e->visible() && !_score->showInvisible()) continue; if (e->isRest() && toRest(e)->isGap()) continue; if (e->isStaffLines()) { Staff* currentStaff = _score->staff(e->staffIdx()); Segment* parent = _score->tick2segment(tick); // Find maximum width for the staff name QList<StaffName>& staffNamesLong = currentStaff->part()->instrument()->longNames(); QString staffName = staffNamesLong.isEmpty() ? " " : staffNamesLong[0].name(); if (staffName == "") { QList<StaffName>& staffNamesShort = currentStaff->part()->instrument()->shortNames(); staffName = staffNamesShort.isEmpty() ? "" : staffNamesShort[0].name(); } Text* newName = new Text(_score); newName->setXmlText(staffName); newName->setParent(parent); newName->setTrack(e->track()); newName->textStyle().setFamily("FreeSans"); newName->textStyle().setSizeIsSpatiumDependent(true); newName->layout(); newName->setPlainText(newName->plainText()); newName->layout(); // Find maximum width for the current Clef Clef* newClef = new Clef(_score); ClefType currentClef = currentStaff->clef(tick); newClef->setClefType(currentClef); newClef->setParent(parent); newClef->setTrack(e->track()); newClef->layout(); if (newClef->width() > _widthClef) _widthClef = newClef->width(); // Find maximum width for the current KeySignature KeySig* newKs = new KeySig(_score); KeySigEvent currentKeySigEvent = currentStaff->keySigEvent(tick); newKs->setKeySigEvent(currentKeySigEvent); // The Parent and the Track must be set to have the key signature layout adjusted to different clefs // This also adds naturals to the key signature (if set in the score style) newKs->setParent(parent); newKs->setTrack(e->track()); newKs->setHideNaturals(true); newKs->layout(); if (newKs->width() > _widthKeySig) _widthKeySig = newKs->width(); // Find maximum width for the current TimeSignature TimeSig* newTs = new TimeSig(_score); // Try to get local time signature, if not, get the current measure one TimeSig* currentTimeSig = currentStaff->timeSig(tick); if (currentTimeSig) newTs->setFrom(currentTimeSig); else newTs->setSig(Fraction(_currentTimeSig.numerator(), _currentTimeSig.denominator()), TimeSigType::NORMAL); newTs->setParent(parent); newTs->setTrack(e->track()); newTs->layout(); if ((newName->width() > lineWidthName) && (newName->xmlText() != "")) lineWidthName = newName->width(); if (newTs->width() > _widthTimeSig) _widthTimeSig = newTs->width(); delete newClef; delete newName; delete newKs; delete newTs; } } _leftMarginTotal = _score->styleP(StyleIdx::clefLeftMargin); _leftMarginTotal += _score->styleP(StyleIdx::keysigLeftMargin); _leftMarginTotal += _score->styleP(StyleIdx::timesigLeftMargin); _newWidth = _widthClef + _widthKeySig + _widthTimeSig + _leftMarginTotal + _panelRightPadding; _xPosMeasure -= _offsetPanel; lineWidthName += _score->spatium() + _score->styleP(StyleIdx::clefLeftMargin) + _widthClef; if (_newWidth < lineWidthName) { _newWidth = lineWidthName; _oldWidth = 0; } if (_oldWidth == 0) { _oldWidth = _newWidth; _width = _newWidth; } else if (_newWidth > 0) { if (_newWidth == _width) { _oldWidth = _width; _width = _newWidth; } else if (((_xPosMeasure <= _newWidth) && (_xPosMeasure >= _oldWidth)) || ((_xPosMeasure >= _newWidth) && (_xPosMeasure <= _oldWidth))) _width = _xPosMeasure; else if (((_xPosMeasure+_measureWidth <= _newWidth) && (_xPosMeasure+_measureWidth >= _oldWidth)) || ((_xPosMeasure+_measureWidth >= _newWidth) && (_xPosMeasure+_measureWidth <= _oldWidth))) _width = _xPosMeasure+_measureWidth; else { _oldWidth = _width; _width = _newWidth; } } _rect = QRect(0, _y, _width, _height); //==================== painter.save(); // Draw colored rectangle painter.setClipping(false); QPointF pos(_offsetPanel, 0); painter.translate(pos); QPen pen; pen.setWidthF(0.0); pen.setStyle(Qt::NoPen); painter.setPen(pen); painter.setBrush(preferences.fgColor); QRectF bg(_rect); bg.setWidth(_widthClef + _widthKeySig + _widthTimeSig + _leftMarginTotal + _panelRightPadding); QPixmap* fgPixmap = _sv->fgPixmap(); if (fgPixmap == 0 || fgPixmap->isNull()) painter.fillRect(bg, preferences.fgColor); else { painter.setMatrixEnabled(false); painter.drawTiledPixmap(bg, *fgPixmap, bg.topLeft() - QPoint(lrint(_sv->matrix().dx()), lrint(_sv->matrix().dy()))); painter.setMatrixEnabled(true); } painter.setClipRect(_rect); painter.setClipping(true); QColor color(MScore::layoutBreakColor); // Draw measure text number QString text = QString("#%1").arg(_currentMeasure->no()+1); Text* newElement = new Text(_score); newElement->setTextStyleType(TextStyleType::DEFAULT); newElement->setFlag(ElementFlag::MOVABLE, false); newElement->setXmlText(text); newElement->textStyle().setFamily("FreeSans"); newElement->textStyle().setSizeIsSpatiumDependent(true); newElement->setColor(color); newElement->sameLayout(); pos = QPointF(_score->styleP(StyleIdx::clefLeftMargin) + _widthClef, _y + newElement->height()); painter.translate(pos); newElement->draw(&painter); pos += QPointF(_offsetPanel, 0); painter.translate(-pos); delete newElement; // This second pass draws the elements spaced evently using the width of the largest element for (const Element* e : el) { if (!e->visible() && !_score->showInvisible()) continue; if (e->isRest() && toRest(e)->isGap()) continue; if (e->isStaffLines()) { painter.save(); Staff* currentStaff = _score->staff(e->staffIdx()); Segment* parent = _score->tick2segmentMM(tick); pos = QPointF (_offsetPanel, e->pagePos().y()); painter.translate(pos); // Draw staff lines StaffLines newStaffLines(*toStaffLines(e)); newStaffLines.setParent(parent); newStaffLines.setTrack(e->track()); newStaffLines.layout(); newStaffLines.setColor(color); newStaffLines.setWidth(bg.width()); newStaffLines.draw(&painter); // Draw barline BarLine barLine(_score); barLine.setBarLineType(BarLineType::NORMAL); barLine.setParent(parent); barLine.setTrack(e->track()); barLine.setSpan(currentStaff->barLineSpan()); barLine.setSpanFrom(currentStaff->barLineFrom()); barLine.setSpanTo(currentStaff->barLineTo()); barLine.layout(); barLine.setColor(color); barLine.draw(&painter); // Draw the current staff name QList<StaffName>& staffNamesLong = currentStaff->part()->instrument()->longNames(); QString staffName = staffNamesLong.isEmpty() ? " " : staffNamesLong[0].name(); if (staffName == "") { QList<StaffName>& staffNamesShort = currentStaff->part()->instrument()->shortNames(); staffName = staffNamesShort.isEmpty() ? "" : staffNamesShort[0].name(); } Text* newName = new Text(_score); newName->setXmlText(staffName); newName->setParent(parent); newName->setTrack(e->track()); newName->setColor(color); newName->textStyle().setFamily("FreeSans"); newName->textStyle().setSizeIsSpatiumDependent(true); newName->layout(); newName->setPlainText(newName->plainText()); newName->layout(); if (currentStaff->part()->staff(0) == currentStaff) { double _spatium = _score->spatium(); pos = QPointF (_score->styleP(StyleIdx::clefLeftMargin) + _widthClef, -_spatium * 2); painter.translate(pos); newName->draw(&painter); painter.translate(-pos); } delete newName; qreal posX = 0.0; // Draw the current Clef Clef clef(_score); clef.setClefType(currentStaff->clef(tick)); clef.setParent(parent); clef.setTrack(e->track()); clef.setColor(color); clef.layout(); posX += _score->styleP(StyleIdx::clefLeftMargin); clef.drawAt(&painter, QPointF(posX, clef.pos().y())); posX += _widthClef; // Draw the current KeySignature KeySig newKs(_score); newKs.setKeySigEvent(currentStaff->keySigEvent(tick)); // The Parent and the track must be set to have the key signature layout adjusted to different clefs // This also adds naturals to the key signature (if set in the score style) newKs.setParent(parent); newKs.setTrack(e->track()); newKs.setColor(color); newKs.setHideNaturals(true); newKs.layout(); posX += _score->styleP(StyleIdx::keysigLeftMargin); newKs.drawAt(&painter, QPointF(posX, 0.0)); posX += _widthKeySig + _xPosTimeSig; // Draw the current TimeSignature TimeSig newTs(_score); // Try to get local time signature, if not, get the current measure one TimeSig* currentTimeSig = currentStaff->timeSig(tick); if (currentTimeSig) { newTs.setFrom(currentTimeSig); newTs.setParent(parent); newTs.setTrack(e->track()); newTs.setColor(color); newTs.layout(); posX += _score->styleP(StyleIdx::timesigLeftMargin); newTs.drawAt(&painter, QPointF(posX, 0.0)); } painter.restore(); } } painter.restore(); _visible = true; }
void Fingering::layout() { if (parent()) { Fraction tick = parent()->tick(); const Staff* st = staff(); if (st && st->isTabStaff(tick) && !st->staffType(tick)->showTabFingering()) { setbbox(QRectF()); return; } } TextBase::layout(); rypos() = 0.0; // handle placement below if (autoplace() && note()) { Note* n = note(); Chord* chord = n->chord(); bool voices = chord->measure()->hasVoices(chord->staffIdx()); bool tight = voices && chord->notes().size() == 1 && !chord->beam() && tid() != Tid::STRING_NUMBER; qreal headWidth = n->bboxRightPos(); // update offset after drag qreal rebase = 0.0; if (offsetChanged() != OffsetChange::NONE) rebase = rebaseOffset(); // temporarily exclude self from chord shape setAutoplace(false); if (layoutType() == ElementType::CHORD) { Stem* stem = chord->stem(); Segment* s = chord->segment(); Measure* m = s->measure(); qreal sp = spatium(); qreal md = minDistance().val() * sp; SysStaff* ss = m->system()->staff(chord->vStaffIdx()); Staff* vStaff = chord->staff(); // TODO: use current height at tick if (n->mirror()) rxpos() -= n->ipos().x(); rxpos() += headWidth * .5; if (placeAbove()) { if (tight) { if (chord->stem()) rxpos() -= 0.8 * sp; rypos() -= 1.5 * sp; } else { QRectF r = bbox().translated(m->pos() + s->pos() + chord->pos() + n->pos() + pos()); SkylineLine sk(false); sk.add(r.x(), r.bottom(), r.width()); qreal d = sk.minDistance(ss->skyline().north()); qreal yd = 0.0; if (d > 0.0 && isStyled(Pid::MIN_DISTANCE)) yd -= d + height() * .25; // force extra space above staff & chord (but not other fingerings) qreal top; if (chord->up() && chord->beam() && stem) { top = stem->y() + stem->bbox().top(); } else { Note* un = chord->upNote(); top = qMin(0.0, un->y() + un->bbox().top()); } top -= md; qreal diff = (bbox().bottom() + ipos().y() + yd + n->y()) - top; if (diff > 0.0) yd -= diff; if (offsetChanged() != OffsetChange::NONE) { // user moved element within the skyline // we may need to adjust minDistance, yd, and/or offset bool inStaff = placeAbove() ? r.bottom() + rebase > 0.0 : r.top() + rebase < staff()->height(); rebaseMinDistance(md, yd, sp, rebase, inStaff); } rypos() += yd; } } else { if (tight) { if (chord->stem()) rxpos() += 0.8 * sp; rypos() += 1.5 * sp; } else { QRectF r = bbox().translated(m->pos() + s->pos() + chord->pos() + n->pos() + pos()); SkylineLine sk(true); sk.add(r.x(), r.top(), r.width()); qreal d = ss->skyline().south().minDistance(sk); qreal yd = 0.0; if (d > 0.0 && isStyled(Pid::MIN_DISTANCE)) yd += d + height() * .25; // force extra space below staff & chord (but not other fingerings) qreal bottom; if (!chord->up() && chord->beam() && stem) { bottom = stem->y() + stem->bbox().bottom(); } else { Note* dn = chord->downNote(); bottom = qMax(vStaff->height(), dn->y() + dn->bbox().bottom()); } bottom += md; qreal diff = bottom - (bbox().top() + ipos().y() + yd + n->y()); if (diff > 0.0) yd += diff; if (offsetChanged() != OffsetChange::NONE) { // user moved element within the skyline // we may need to adjust minDistance, yd, and/or offset bool inStaff = placeAbove() ? r.bottom() + rebase > 0.0 : r.top() + rebase < staff()->height(); rebaseMinDistance(md, yd, sp, rebase, inStaff); } rypos() += yd; } } } else if (tid() == Tid::LH_GUITAR_FINGERING) { // place to left of note qreal left = n->shape().left(); if (left - n->x() > 0.0) rxpos() -= left; else rxpos() -= n->x(); } // for other fingering styles, do not autoplace // restore autoplace setAutoplace(true); } else if (offsetChanged() != OffsetChange::NONE) { // rebase horizontally too, as autoplace may have adjusted it rebaseOffset(false); } setOffsetChanged(false); }
void System::layout2() { VBox* b = vbox(); if (b) { b->layout(); setbbox(b->bbox()); return; } setPos(0.0, 0.0); QList<std::pair<int,SysStaff*>> visibleStaves; int firstStaffIdx = -1; int lastStaffIdx = 0; int firstStaffInitialIdx = -1; int lastStaffInitialIdx = 0; Measure* fm = firstMeasure(); for (int i = 0; i < _staves.size(); ++i) { Staff* s = score()->staff(i); SysStaff* ss = _staves[i]; if (s->show() && ss->show()) { visibleStaves.append(std::pair<int,SysStaff*>(i, ss)); if (firstStaffIdx == -1) firstStaffIdx = i; if (i > lastStaffIdx) lastStaffIdx = i; if (fm && fm->visible(i)) { if (firstStaffInitialIdx == -1) firstStaffInitialIdx = i; lastStaffInitialIdx = i; } } else { ss->setbbox(QRectF()); // already done in layout() ? } } if (firstStaffIdx == -1) firstStaffIdx = 0; if (firstStaffInitialIdx == -1) firstStaffInitialIdx = 0; qreal _spatium = spatium(); qreal y = 0.0; qreal minVerticalDistance = score()->styleP(StyleIdx::minVerticalDistance); qreal staffDistance = score()->styleP(StyleIdx::staffDistance); qreal akkoladeDistance = score()->styleP(StyleIdx::akkoladeDistance); if (visibleStaves.empty()) { qDebug("====no visible staves, staves %d, score staves %d", _staves.size(), score()->nstaves()); } for (auto i = visibleStaves.begin();; ++i) { SysStaff* ss = i->second; int si1 = i->first; Staff* staff = score()->staff(si1); auto ni = i + 1; qreal h = staff->height(); if (ni == visibleStaves.end()) { ss->setYOff(staff->lines() == 1 ? _spatium * staff->mag() : 0.0); ss->bbox().setRect(_leftMargin, y, width() - _leftMargin, h); break; } int si2 = ni->first; qreal dist = h; switch (staff->innerBracket()) { case BracketType::BRACE: dist += akkoladeDistance; break; case BracketType::NORMAL: case BracketType::SQUARE: case BracketType::LINE: case BracketType::NO_BRACKET: dist += staffDistance; break; } dist += score()->staff(si2)->userDist(); for (MeasureBase* mb : ml) { if (!mb->isMeasure()) continue; Measure* m = toMeasure(mb); Shape& s1 = m->staffShape(si1); Shape& s2 = m->staffShape(si2); qreal d = s1.minVerticalDistance(s2) + minVerticalDistance; dist = qMax(dist, d); Spacer* sp = m->mstaff(si1)->_vspacerDown; if (sp) { if (sp->spacerType() == SpacerType::FIXED) { dist = staff->height() + sp->gap(); break; } else dist = qMax(dist, staff->height() + sp->gap()); } sp = m->mstaff(si2)->_vspacerUp; if (sp) dist = qMax(dist, sp->gap()); } ss->setYOff(staff->lines() == 1 ? _spatium * staff->mag() : 0.0); ss->bbox().setRect(_leftMargin, y, width() - _leftMargin, h); y += dist; } qreal systemHeight = staff(lastStaffIdx)->bbox().bottom(); setHeight(systemHeight); for (MeasureBase* m : ml) { if (m->isMeasure()) { // note that the factor 2 * _spatium must be corrected for when exporting // system distance in MusicXML (issue #24733) m->bbox().setRect(0.0, -_spatium, m->width(), systemHeight + 2.0 * _spatium); } else if (m->isHBox()) { m->bbox().setRect(0.0, 0.0, m->width(), systemHeight); toHBox(m)->layout2(); } else if (m->isTBox()) { // m->bbox().setRect(0.0, 0.0, m->width(), systemHeight); toTBox(m)->layout(); } else qDebug("unhandled measure type %s", m->name()); } if (fm) { Segment* s = fm->first(); BarLine* _barLine = s->isBeginBarLineType() ? toBarLine(s->element(0)) : 0; if (_barLine) { _barLine->setTrack(firstStaffInitialIdx * VOICES); _barLine->setSpan(lastStaffInitialIdx - firstStaffInitialIdx + 1); if (score()->staff(firstStaffInitialIdx)->lines() == 1) _barLine->setSpanFrom(BARLINE_SPAN_1LINESTAFF_FROM); else _barLine->setSpanFrom(0); int llines = score()->staff(lastStaffInitialIdx)->lines(); int spanTo = llines == 1 ? BARLINE_SPAN_1LINESTAFF_TO : (llines - 1) * 2; _barLine->setSpanTo(spanTo); _barLine->layout(); } } //--------------------------------------------------- // layout brackets vertical position //--------------------------------------------------- for (Bracket* b : _brackets) { int staffIdx1 = b->firstStaff(); int staffIdx2 = b->lastStaff(); qreal sy = 0; // assume bracket not visible qreal ey = 0; // if start staff not visible, try next staff while (staffIdx1 <= staffIdx2 && !_staves[staffIdx1]->show()) ++staffIdx1; // if end staff not visible, try prev staff while (staffIdx1 <= staffIdx2 && !_staves[staffIdx2]->show()) --staffIdx2; // the bracket will be shown IF: // it spans at least 2 visible staves (staffIdx1 < staffIdx2) OR // it spans just one visible staff (staffIdx1 == staffIdx2) but it is required to do so // (the second case happens at least when the bracket is initially dropped) bool notHidden = (staffIdx1 < staffIdx2) || (b->span() == 1 && staffIdx1 == staffIdx2); if (notHidden) { // set vert. pos. and height to visible spanned staves sy = _staves[staffIdx1]->bbox().top(); ey = _staves[staffIdx2]->bbox().bottom(); } b->rypos() = sy; // if (score()->staff(firstStaffInitialIdx)->lines() == 1) // bbox of one line staff bad? // b->rypos() -= _spatium; b->setHeight(ey - sy); b->layout(); } //--------------------------------------------------- // layout instrument names //--------------------------------------------------- int staffIdx = 0; for (Part* p : score()->parts()) { SysStaff* s = staff(staffIdx); SysStaff* s2; int nstaves = p->nstaves(); if (s->show()) { for (InstrumentName* t : s->instrumentNames) { // // override Text->layout() // qreal y1, y2; switch (t->layoutPos()) { default: case 0: // center at part y1 = s->bbox().top(); s2 = staff(staffIdx); for (int i = staffIdx + nstaves - 1; i > 0; --i) { SysStaff* s = staff(i); if (s->show()) { s2 = s; break; } } y2 = s2->bbox().bottom(); break; case 1: // center at first staff y1 = s->bbox().top(); y2 = s->bbox().bottom(); break; // TODO: // sort out invisible staves case 2: // center between first and second staff y1 = s->bbox().top(); y2 = staff(staffIdx + 1)->bbox().bottom(); break; case 3: // center at second staff y1 = staff(staffIdx + 1)->bbox().top(); y2 = staff(staffIdx + 1)->bbox().bottom(); break; case 4: // center between first and second staff y1 = staff(staffIdx + 1)->bbox().top(); y2 = staff(staffIdx + 2)->bbox().bottom(); break; case 5: // center at third staff y1 = staff(staffIdx + 2)->bbox().top(); y2 = staff(staffIdx + 2)->bbox().bottom(); break; } t->rypos() = y1 + (y2 - y1) * .5 + t->textStyle().offset(t->spatium()).y(); } } staffIdx += nstaves; } }
void System::layoutSystem(qreal xo1) { if (_staves.empty()) // ignore vbox return; static const Spatium instrumentNameOffset(1.0); // TODO: make style value int nstaves = _staves.size(); //--------------------------------------------------- // find x position of staves // create brackets //--------------------------------------------------- qreal xoff2 = 0.0; // x offset for instrument name int bracketLevels = 0; for (int idx = 0; idx < nstaves; ++idx) bracketLevels = qMax(bracketLevels, score()->staff(idx)->bracketLevels()); qreal bracketWidth[bracketLevels]; for (int i = 0; i < bracketLevels; ++i) bracketWidth[i] = 0.0; QList<Bracket*> bl; bl.swap(_brackets); for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) { Staff* s = score()->staff(staffIdx); for (int i = 0; i < bracketLevels; ++i) { if (s->bracket(i) == BracketType::NO_BRACKET) continue; int firstStaff = staffIdx; int lastStaff = staffIdx + s->bracketSpan(i) - 1; if (lastStaff >= nstaves) lastStaff = nstaves - 1; for (; firstStaff <= lastStaff; ++firstStaff) { if (score()->staff(firstStaff)->show()) break; } for (; lastStaff >= firstStaff; --lastStaff) { if (score()->staff(lastStaff)->show()) break; } int span = lastStaff - firstStaff + 1; // // do not show bracket if it only spans one // system due to some invisible staves // if ((span > 1) || (s->bracketSpan(i) == span)) { // // this bracket is visible // Bracket* b = 0; int track = staffIdx * VOICES; for (int k = 0; k < bl.size(); ++k) { if (bl[k]->track() == track && bl[k]->level() == i) { b = bl.takeAt(k); break; } } if (b == 0) { b = new Bracket(score()); b->setGenerated(true); b->setTrack(track); b->setLevel(i); } add(b); b->setFirstStaff(firstStaff); b->setLastStaff(lastStaff); b->setBracketType(s->bracket(i)); b->setSpan(s->bracketSpan(i)); bracketWidth[i] = qMax(bracketWidth[i], b->width()); } } if (!s->show()) continue; for (InstrumentName* t : _staves[staffIdx]->instrumentNames) { t->layout(); qreal w = t->width() + point(instrumentNameOffset); if (w > xoff2) xoff2 = w; } } for (Bracket* b : bl) delete b; //--------------------------------------------------- // layout SysStaff and StaffLines //--------------------------------------------------- _leftMargin = xoff2; qreal bd = score()->styleP(StyleIdx::bracketDistance); if ( _brackets.size() > 0) { for (int i = 0; i < bracketLevels; ++i) _leftMargin += bracketWidth[i] + bd; } int nVisible = 0; for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) { SysStaff* s = _staves[staffIdx]; Staff* staff = score()->staff(staffIdx); if (!staff->show() || !s->show()) { s->setbbox(QRectF()); continue; } ++nVisible; qreal staffMag = staff->mag(); qreal h; if (staff->lines() == 1) h = 2; else h = (staff->lines()-1) * staff->lineDistance(); h = h * staffMag * spatium(); s->bbox().setRect(_leftMargin + xo1, 0.0, 0.0, h); } //--------------------------------------------------- // layout brackets //--------------------------------------------------- for (Bracket* b : _brackets) { qreal xo = -xo1; for (const Bracket* b2 : _brackets) { if (b->level() > b2->level() && ((b->firstStaff() >= b2->firstStaff() && b->firstStaff() <= b2->lastStaff()) || (b->lastStaff() >= b2->firstStaff() && b->lastStaff() <= b2->lastStaff()))) xo += b2->width() + bd; } b->rxpos() = _leftMargin - xo - b->width(); } //--------------------------------------------------- // layout instrument names x position //--------------------------------------------------- int idx = 0; for (const Part* p : score()->parts()) { SysStaff* s = staff(idx); if (s->show() && p->show()) { for (InstrumentName* t : s->instrumentNames) { switch (t->textStyle().align() & AlignmentFlags::HMASK) { case int(AlignmentFlags::LEFT): t->rxpos() = 0; break; case int(AlignmentFlags::HCENTER): t->rxpos() = (xoff2 - point(instrumentNameOffset) + xo1) * .5; break; case int(AlignmentFlags::RIGHT): default: t->rxpos() = xoff2 - point(instrumentNameOffset) + xo1; break; } t->rxpos() += t->textStyle().offset(t->spatium()).x(); } } idx += p->nstaves(); } }
void PositionCursor::move(int tick) { QRectF r(bbox()); // // set mark height for whole system // if (_type == CursorType::LOOP_OUT) tick --; Score* score = _sv->score(); Measure* measure = score->tick2measureMM(tick); if (measure == 0) return; qreal x; int offset = 0; Segment* s; for (s = measure->first(Segment::Type::ChordRest); s;) { int t1 = s->tick(); int x1 = s->canvasPos().x(); qreal x2; int t2; Segment* ns = s->next(Segment::Type::ChordRest); if (ns) { t2 = ns->tick(); x2 = ns->canvasPos().x(); } else { t2 = measure->endTick(); x2 = measure->canvasPos().x() + measure->width(); } t1 += offset; t2 += offset; if (tick >= t1 && tick < t2) { int dt = t2 - t1; qreal dx = x2 - x1; x = x1 + dx * (tick-t1) / dt; break; } s = ns; } if (s == 0) return; System* system = measure->system(); if (system == 0) return; double y = system->staffYpage(0) + system->page()->pos().y(); double _spatium = score->spatium(); qreal mag = _spatium / (MScore::DPI * SPATIUM20); double w = (_spatium * 2.0 + score->scoreFont()->width(SymId::noteheadBlack, mag))/3; double h = 6 * _spatium; // // set cursor height for whole system // double y2 = 0.0; for (int i = 0; i < score->nstaves(); ++i) { SysStaff* ss = system->staff(i); if (!ss->show() || !score->staff(i)->show()) continue; y2 = ss->y() + ss->bbox().height(); } h += y2; y -= 3 * _spatium; if (_type == CursorType::LOOP_IN) { x = x - _spatium + w/1.5; } else { x = x - _spatium * .5; } _tick = tick; _rect = QRectF(x, y, w, h); _sv->update(_sv->matrix().mapRect(r | bbox()).toRect().adjusted(-1,-1,1,1)); }
void System::layout2() { if (isVbox()) // ignore vbox return; int nstaves = _staves.size(); qreal _spatium = spatium(); qreal y = 0.0; int lastStaffIdx = 0; // last visible staff int firstStaffIdx = -1; qreal lastStaffDistanceDown = 0.0; for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) { Staff* staff = score()->staff(staffIdx); StyleIdx downDistance; qreal userDist = 0.0; if ((staffIdx + 1) == nstaves) { // // last staff in system // MeasureBase* mb = ml.last(); bool nextMeasureIsVBOX = false; if (mb->next()) { Element::Type type = mb->next()->type(); if (type == Element::Type::VBOX || type == Element::Type::TBOX || type == Element::Type::FBOX) nextMeasureIsVBOX = true; } downDistance = nextMeasureIsVBOX ? StyleIdx::systemFrameDistance : StyleIdx::minSystemDistance; } else if (staff->rstaff() < (staff->part()->staves()->size()-1)) { // // staff is not last staff in a part // downDistance = StyleIdx::akkoladeDistance; userDist = score()->staff(staffIdx + 1)->userDist(); } else { downDistance = StyleIdx::staffDistance; userDist = score()->staff(staffIdx + 1)->userDist(); } SysStaff* s = _staves[staffIdx]; qreal distDown = score()->styleS(downDistance).val() * _spatium + userDist; qreal nominalDistDown = distDown; qreal distUp = 0.0; int n = ml.size(); for (int i = 0; i < n; ++i) { MeasureBase* m = ml.at(i); distDown = qMax(distDown, m->distanceDown(staffIdx)); distUp = qMax(distUp, m->distanceUp(staffIdx)); } s->setDistanceDown(distDown); s->setDistanceUp(distUp); if (!staff->show() || !s->show()) { s->setbbox(QRectF()); // already done in layout() ? continue; } qreal sHeight = staff->height(); qreal dup = staffIdx == 0 ? 0.0 : s->distanceUp(); if (staff->lines() == 1) dup -= _spatium * staff->mag(); s->bbox().setRect(_leftMargin, y + dup, width() - _leftMargin, sHeight); y += dup + sHeight + s->distanceDown(); lastStaffIdx = staffIdx; lastStaffDistanceDown = distDown - nominalDistDown; if (firstStaffIdx == -1) firstStaffIdx = staffIdx; } if (firstStaffIdx == -1) firstStaffIdx = 0; qreal systemHeight = staff(lastStaffIdx)->bbox().bottom(); if (lastStaffIdx < nstaves - 1) systemHeight += lastStaffDistanceDown; setHeight(systemHeight); int n = ml.size(); for (int i = 0; i < n; ++i) { MeasureBase* m = ml.at(i); if (m->type() == Element::Type::MEASURE) { // note that the factor 2 * _spatium must be corrected for when exporting // system distance in MusicXML (issue #24733) m->bbox().setRect(0.0, -_spatium, m->width(), systemHeight + 2 * _spatium); } else if (m->type() == Element::Type::HBOX) { m->bbox().setRect(0.0, 0.0, m->width(), systemHeight); static_cast<HBox*>(m)->layout2(); } } if (_barLine) { _barLine->setTrack(firstStaffIdx * VOICES); _barLine->setSpan(lastStaffIdx - firstStaffIdx + 1); if (score()->staff(0)->lines() == 1) _barLine->setSpanFrom(BARLINE_SPAN_1LINESTAFF_FROM); int spanTo = (score()->staff(lastStaffIdx)->lines() == 1) ? BARLINE_SPAN_1LINESTAFF_TO : (score()->staff(lastStaffIdx)->lines()-1)*2; _barLine->setSpanTo(spanTo); _barLine->layout(); } //--------------------------------------------------- // layout brackets vertical position //--------------------------------------------------- n = _brackets.size(); for (int i = 0; i < n; ++i) { Bracket* b = _brackets.at(i); int staffIdx1 = b->firstStaff(); int staffIdx2 = b->lastStaff(); qreal sy = 0; // assume bracket not visible qreal ey = 0; // if start staff not visible, try next staff while (staffIdx1 <= staffIdx2 && !_staves[staffIdx1]->show()) ++staffIdx1; // if end staff not visible, try prev staff while (staffIdx1 <= staffIdx2 && !_staves[staffIdx2]->show()) --staffIdx2; // the bracket will be shown IF: // it spans at least 2 visible staves (staffIdx1 < staffIdx2) OR // it spans just one visible staff (staffIdx1 == staffIdx2) but it is required to do so // (the second case happens at least when the bracket is initially dropped) bool notHidden = (staffIdx1 < staffIdx2) || (b->span() == 1 && staffIdx1 == staffIdx2); if (notHidden) { // set vert. pos. and height to visible spanned staves sy = _staves[staffIdx1]->bbox().top(); ey = _staves[staffIdx2]->bbox().bottom(); } b->rypos() = sy; b->setHeight(ey - sy); b->layout(); } //--------------------------------------------------- // layout instrument names //--------------------------------------------------- int staffIdx = 0; n = score()->parts().size(); for (Part* p : score()->parts()) { SysStaff* s = staff(staffIdx); SysStaff* s2; int nstaves = p->nstaves(); if (s->show()) { for (InstrumentName* t : s->instrumentNames) { // // override Text->layout() // qreal y1, y2; switch (t->layoutPos()) { default: case 0: // center at part y1 = s->bbox().top(); s2 = staff(staffIdx); for (int i = staffIdx + nstaves - 1; i > 0; --i) { SysStaff* s = staff(i); if (s->show()) { s2 = s; break; } } y2 = s2->bbox().bottom(); break; case 1: // center at first staff y1 = s->bbox().top(); y2 = s->bbox().bottom(); break; // TODO: // sort out invisible staves case 2: // center between first and second staff y1 = s->bbox().top(); y2 = staff(staffIdx + 1)->bbox().bottom(); break; case 3: // center at second staff y1 = staff(staffIdx + 1)->bbox().top(); y2 = staff(staffIdx + 1)->bbox().bottom(); break; case 4: // center between first and second staff y1 = staff(staffIdx + 1)->bbox().top(); y2 = staff(staffIdx + 2)->bbox().bottom(); break; case 5: // center at third staff y1 = staff(staffIdx + 2)->bbox().top(); y2 = staff(staffIdx + 2)->bbox().bottom(); break; } t->rypos() = y1 + (y2 - y1) * .5 + t->textStyle().offset(t->spatium()).y(); } } staffIdx += nstaves; } }
void ContinuousPanel::paint(const QRect& /*r*/, QPainter& p) { if (!_active) { _visible = false; return; } Measure* measure = _score->tick2measure(0); if (measure == 0){ _visible = false; return; } if (measure->mmRest()) { measure = measure->mmRest(); _mmRestCount = measure->mmRestCount(); } System* system = measure->system(); if (system == 0) { _visible = false; return; } Segment* s = _score->tick2segment(0); double _spatium = _score->spatium(); _x = 0; if (_width <= 0) _width = s->x(); // // Set panel height for whole system // _height = 6 * _spatium; _y = system->staffYpage(0) + system->page()->pos().y(); double y2 = 0.0; for (int i = 0; i < _score->nstaves(); ++i) { SysStaff* ss = system->staff(i); if (!ss->show() || !_score->staff(i)->show()) continue; y2 = ss->y() + ss->bbox().height(); } _height += y2 + 6*_spatium; _y -= 6 * _spatium; // // Check elements at current panel position // _offsetPanel = -(_sv->xoffset()) / _sv->pmag(); _rect = QRect(_offsetPanel + _width, _y, 1, _height); //qDebug() << "width=" << _width << "_y="<< _y << "_offsetPanel=" << _offsetPanel << "_sv->xoffset()" << _sv->xoffset() << "_sv->pmag()" << _sv->pmag() <<"_spatium" << _spatium << "s->canvasPos().x()" << s->canvasPos().x() << "s->x()" << s->x(); Page* page = _score->pages().front(); QList<Element*> elementsCurrent = page->items(_rect); if (elementsCurrent.empty()) { _visible = false; return; } qStableSort(elementsCurrent.begin(), elementsCurrent.end(), elementLessThan); _currentMeasure = nullptr; for (const Element* e : elementsCurrent) { e->itemDiscovered = 0; if (!e->visible()) { if (_score->printing() || !_score->showInvisible()) continue; } if (e->type() == Element::Type::MEASURE) { _currentMeasure = static_cast<const Measure*>(e); _currentTimeSig = _currentMeasure->timesig(); _currentMeasureTick = _currentMeasure->tick(); _currentMeasureNo = _currentMeasure->no(); // Find number of multi measure rests to display in the panel if (_currentMeasure->isMMRest()) _mmRestCount = _currentMeasure->mmRestCount(); else if (_currentMeasure->mmRest()) _mmRestCount = _currentMeasure->mmRest()->mmRestCount(); else _mmRestCount = 0; _xPosMeasure = e->canvasX(); _measureWidth = e->width(); break; } } if (_currentMeasure == nullptr) return; findElementWidths(elementsCurrent); // Don't show panel if staff names are visible if (_sv->xoffset() / _sv->pmag() + _xPosMeasure > 0) { _visible = false; return; } //qDebug() << "_sv->xoffset()=" <<_sv->xoffset() << " _sv->pmag()="<< _sv->pmag() <<" s->x=" << s->x() << " width=" << _width << " currentMeasue=" << _currentMeasure->x() << " _xPosMeasure=" << _xPosMeasure; draw(p, elementsCurrent); _visible = true; }