From 2a8c889186de91be816539042760d2ac1b90763a Mon Sep 17 00:00:00 2001 From: Niek van den Berg Date: Fri, 19 Feb 2021 12:06:42 +0100 Subject: [PATCH] Port of PR #7529 to master. Reimplement spacers in vertical staves adjustment to make sure all spacers are taken into account. --- src/libmscore/layout.cpp | 84 +++++++++++++++++++++++++++------------- src/libmscore/layout.h | 4 +- src/libmscore/system.cpp | 6 --- src/libmscore/system.h | 2 - 4 files changed, 61 insertions(+), 35 deletions(-) diff --git a/src/libmscore/layout.cpp b/src/libmscore/layout.cpp index 5a2cb6cd29f0f..e60b7c29447e7 100644 --- a/src/libmscore/layout.cpp +++ b/src/libmscore/layout.cpp @@ -1658,8 +1658,8 @@ static void distributeStaves(Page* page) int ngaps { 0 }; qreal prevYBottom { page->tm() }; qreal yBottom { 0.0 }; - bool vbox { false }; - Spacer* activeSpacer { nullptr }; + bool vbox { false }; + Spacer* nextSpacer { nullptr }; bool transferNormalBracket { false }; bool transferCurlyBracket { false }; for (System* system : page->systems()) { @@ -1697,8 +1697,30 @@ static void distributeStaves(Page* page) continue; } + Spacer* activeSpacer { nextSpacer }; + nextSpacer = nullptr; + for (MeasureBase* mb : system->measures()) { + Measure* m = toMeasure(mb); + Spacer* sp = m->vspacerUp(staff->idx()); + if (sp) { + if (!activeSpacer || ((activeSpacer->spacerType() == SpacerType::UP) && (sp->gap() > activeSpacer->gap()))) { + activeSpacer = sp; + } + continue; + } + sp = m->vspacerDown(staff->idx()); + if (sp) { + if (sp->spacerType() == SpacerType::FIXED) { + nextSpacer = sp; + } else { + if (!nextSpacer || (sp->gap() > nextSpacer->gap())) { + nextSpacer = sp; + } + } + } + } + VerticalGapData* vgd = new VerticalGapData(!ngaps++, system, staff, sysStaff, activeSpacer, prevYBottom); - activeSpacer = nullptr; if (newSystem) { vgd->addSpaceBetweenSections(); @@ -1729,13 +1751,12 @@ static void distributeStaves(Page* page) transferNormalBracket = endNormalBracket >= 0; transferCurlyBracket = endCurlyBracket >= 0; } - activeSpacer = system->getActiveSpacer(); } --ngaps; qreal spaceLeft { page->height() - page->bm() - score->styleP(Sid::staffLowerBorder) - yBottom }; - if (activeSpacer) { - spaceLeft -= activeSpacer->gap(); + if (nextSpacer && (nextSpacer->spacerType() == SpacerType::DOWN)) { + spaceLeft -= nextSpacer->gap(); } if (spaceLeft <= 0.0) { return; @@ -1787,17 +1808,19 @@ static void distributeStaves(Page* page) } // If there is still space left, distribute the space of the staves. + // However, there is a limit on how much space is added per gap. const qreal maxPageFill { score->styleP(Sid::maxPageFillSpread) }; + spaceLeft = qMin(maxPageFill * vgdl.length(), spaceLeft); pass = 0; ngaps = 1; while (!almostZero(spaceLeft) && !almostZero(maxPageFill) && (ngaps > 0) && (++pass < maxPasses)) { ngaps = 0; qreal addedSpace { 0.0 }; + qreal step { spaceLeft / vgdl.sumStretchFactor() }; for (VerticalGapData* vgd : vgdl) { - qreal step = spaceLeft / vgdl.sumStretchFactor(); - step = vgd->addFillSpacing(step, maxPageFill); - if (!almostZero(step)) { - addedSpace += step * vgd->factor(); + qreal res { vgd->addFillSpacing(step, maxPageFill) }; + if (!almostZero(res)) { + addedSpace += res * vgd->factor(); ++ngaps; } } @@ -5429,6 +5452,7 @@ LayoutContext::~LayoutContext() //--------------------------------------------------------- // VerticalStretchData +// defines a gap ABOVE the staff. //--------------------------------------------------------- VerticalGapData::VerticalGapData(bool first, System* sys, Staff* st, SysStaff* sst, const Spacer* spacer, qreal y) @@ -5438,13 +5462,15 @@ VerticalGapData::VerticalGapData(bool first, System* sys, Staff* st, SysStaff* s _normalisedSpacing = system->score()->styleP(Sid::staffUpperBorder); _maxActualSpacing = _normalisedSpacing; } else { + _normalisedSpacing = system->y() + (sysStaff ? sysStaff->y() : 0.0) - y; + _maxActualSpacing = system->score()->styleP(Sid::maxStaffSpread); if (spacer) { - _fixedHeight = true; - _normalisedSpacing = spacer->gap(); - _maxActualSpacing = _normalisedSpacing; - } else { - _normalisedSpacing = system->y() + (sysStaff ? sysStaff->y() : 0.0) - y; - _maxActualSpacing = system->score()->styleP(Sid::maxStaffSpread); + _hasSpacer = true; + _fixedSpacer = spacer->spacerType() == SpacerType::FIXED; + _normalisedSpacing = qMax(_normalisedSpacing, spacer->gap()); + if (_fixedSpacer) { + _maxActualSpacing = _normalisedSpacing; + } } } } @@ -5470,8 +5496,8 @@ void VerticalGapData::updateFactor(qreal factor) void VerticalGapData::addSpaceBetweenSections() { updateFactor(system->score()->styleD(Sid::spreadSystem)); - if (!_fixedHeight) { - _maxActualSpacing = qMax(_maxActualSpacing, system->score()->styleP(Sid::maxSystemSpread)); + if (!(_fixedHeight | _fixedSpacer)) { + _maxActualSpacing = system->score()->styleP(Sid::maxSystemSpread) / _factor; } } @@ -5485,7 +5511,7 @@ void VerticalGapData::addSpaceAroundVBox(bool above) _factor = 1.0; const Score* score { system->score() }; _normalisedSpacing = above ? score->styleP(Sid::frameSystemDistance) : score->styleP(Sid::systemFrameDistance); - _maxActualSpacing = _normalisedSpacing; + _maxActualSpacing = _normalisedSpacing / _factor; } //--------------------------------------------------------- @@ -5512,7 +5538,7 @@ void VerticalGapData::addSpaceAroundCurlyBracket() void VerticalGapData::insideCurlyBracket() { - _maxActualSpacing = system->score()->styleP(Sid::maxAkkoladeDistance); + _maxActualSpacing = system->score()->styleP(Sid::maxAkkoladeDistance) / _factor; } //--------------------------------------------------------- @@ -5549,10 +5575,10 @@ qreal VerticalGapData::actualAddedSpace() const qreal VerticalGapData::addSpacing(qreal step) { - if (_fixedHeight) { + if (_fixedHeight | _fixedSpacer) { return 0.0; } - if ((_normalisedSpacing >= _maxActualSpacing)) { + if (_normalisedSpacing >= _maxActualSpacing) { _normalisedSpacing = _maxActualSpacing; step = 0.0; } else { @@ -5572,7 +5598,7 @@ qreal VerticalGapData::addSpacing(qreal step) bool VerticalGapData::isFixedHeight() const { - return _fixedHeight; + return _fixedHeight || almostZero(_normalisedSpacing - _maxActualSpacing); } //--------------------------------------------------------- @@ -5591,8 +5617,12 @@ void VerticalGapData::undoLastAddSpacing() qreal VerticalGapData::addFillSpacing(qreal step, qreal maxFill) { - qreal res = addSpacing(qMin(maxFill - _fillSpacing, step)); - _fillSpacing += res; + if (_fixedSpacer) { + return 0.0; + } + qreal actStep { ((step + _fillSpacing / _factor) > maxFill) ? (maxFill - _fillSpacing / _factor) : step }; + qreal res = addSpacing(actStep); + _fillSpacing += res * _factor; return res; } @@ -5615,7 +5645,9 @@ qreal VerticalGapDataList::sumStretchFactor() const { qreal sum { 0.0 }; for (VerticalGapData* vsd : *this) { - sum += vsd->factor(); + if (!vsd->isFixedHeight()) { + sum += vsd->factor(); + } } return sum; } diff --git a/src/libmscore/layout.h b/src/libmscore/layout.h index 80328b51bd811..ff174b0bdddb0 100644 --- a/src/libmscore/layout.h +++ b/src/libmscore/layout.h @@ -30,7 +30,9 @@ class Page; class VerticalGapData { private: - bool _fixedHeight { false }; + bool _fixedHeight { false }; + bool _hasSpacer { false }; + bool _fixedSpacer { false }; qreal _factor { 1.0 }; qreal _normalisedSpacing { 0.0 }; qreal _maxActualSpacing { 0.0 }; diff --git a/src/libmscore/system.cpp b/src/libmscore/system.cpp index 3aec219f3d2dc..294b551e32e71 100644 --- a/src/libmscore/system.cpp +++ b/src/libmscore/system.cpp @@ -1581,22 +1581,16 @@ qreal System::spacerDistance(bool up) const return 0.0; } qreal dist = 0.0; - activeSpacer = nullptr; for (MeasureBase* mb : measures()) { if (mb->isMeasure()) { Measure* m = toMeasure(mb); Spacer* sp = up ? m->vspacerUp(staff) : m->vspacerDown(staff); if (sp) { if (sp->spacerType() == SpacerType::FIXED) { - activeSpacer = sp; dist = sp->gap(); break; } else { dist = qMax(dist, sp->gap()); - if (sp->gap() > dist) { - activeSpacer = sp; - dist = sp->gap(); - } } } } diff --git a/src/libmscore/system.h b/src/libmscore/system.h index e76be05071442..1e497009b27c0 100644 --- a/src/libmscore/system.h +++ b/src/libmscore/system.h @@ -98,7 +98,6 @@ class System final : public Element qreal _leftMargin { 0.0 }; ///< left margin for instrument name, brackets etc. mutable bool fixedDownDistance { false }; - mutable Spacer* activeSpacer { nullptr }; qreal _distance { 0.0 }; /// temp. variable used during layout qreal _systemHeight { 0.0 }; @@ -200,7 +199,6 @@ class System final : public Element void moveBracket(int staffIdx, int srcCol, int dstCol); bool hasFixedDownDistance() const { return fixedDownDistance; } - Spacer* getActiveSpacer() const { return activeSpacer; } int firstVisibleStaff() const; int nextVisibleStaff(int) const; qreal distance() const { return _distance; }