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; } }