Skip to content

Commit 3d9c008

Browse files
Merge pull request #17951 from mike-spa/restsImprovement
Rests improvement
2 parents d57b0eb + 29b5a73 commit 3d9c008

File tree

4 files changed

+70
-7
lines changed

4 files changed

+70
-7
lines changed

src/engraving/layout/v0/chordlayout.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2736,14 +2736,16 @@ void ChordLayout::resolveVerticalRestConflicts(Score* score, Segment* segment, s
27362736

27372737
collectChordsAndRest(segment, staffIdx, chords, rests);
27382738

2739-
for (Rest* rest : rests) {
2740-
rest->verticalClearance().reset();
2741-
}
2742-
27432739
if (rests.empty()) {
27442740
return;
27452741
}
27462742

2743+
collectChordsOverlappingRests(segment, staffIdx, chords);
2744+
2745+
for (Rest* rest : rests) {
2746+
rest->verticalClearance().reset();
2747+
}
2748+
27472749
if (!chords.empty()) {
27482750
resolveRestVSChord(rests, chords, score, segment, staffIdx);
27492751
}
@@ -2763,7 +2765,7 @@ void ChordLayout::resolveRestVSChord(std::vector<Rest*>& rests, std::vector<Chor
27632765
int lines = staff->lines(tick);
27642766
double spatium = staff->spatium(tick);
27652767
double lineDistance = staff->lineDistance(tick) * spatium;
2766-
const double minRestToChordClearance = 0.35 * spatium;
2768+
double minRestToChordClearance = 0.35 * spatium;
27672769

27682770
for (Rest* rest : rests) {
27692771
if (!rest->visible() || !rest->autoplace()) {
@@ -2774,14 +2776,25 @@ void ChordLayout::resolveRestVSChord(std::vector<Rest*>& rests, std::vector<Chor
27742776
if (!chord->visible() || !chord->autoplace()) {
27752777
continue;
27762778
}
2779+
27772780
bool restAbove = rest->voice() < chord->voice() || (chord->slash() && !(rest->voice() % 2));
27782781
int upSign = restAbove ? -1 : 1;
27792782
double restYOffset = rest->offset().y();
27802783
bool ignoreYOffset = (restAbove && restYOffset > 0) || (!restAbove && restYOffset < 0);
27812784
PointF offset = ignoreYOffset ? PointF(0, restYOffset) : PointF(0, 0);
2785+
2786+
double clearance = 0.0;
27822787
Shape restShape = rest->shape().translated(rest->pos() - offset);
2783-
Shape chordShape = chord->shape().translated(chord->pos());
2784-
double clearance = restAbove ? restShape.verticalClearance(chordShape) : chordShape.verticalClearance(restShape);
2788+
if (chord->segment() == rest->segment()) {
2789+
Shape chordShape = chord->shape().translated(chord->pos());
2790+
clearance = restAbove ? restShape.verticalClearance(chordShape) : chordShape.verticalClearance(restShape);
2791+
} else {
2792+
Note* limitNote = restAbove ? chord->upNote() : chord->downNote();
2793+
Shape noteShape = limitNote->shape().translate(limitNote->pos());
2794+
clearance = restAbove ? noteShape.top() - restShape.bottom() : restShape.top() - noteShape.bottom();
2795+
minRestToChordClearance = 0.0;
2796+
}
2797+
27852798
double margin = clearance - minRestToChordClearance;
27862799
int marginInSteps = floor(margin / lineDistance);
27872800
if (restAbove) {
@@ -2792,6 +2805,7 @@ void ChordLayout::resolveRestVSChord(std::vector<Rest*>& rests, std::vector<Chor
27922805
if (margin > 0) {
27932806
continue;
27942807
}
2808+
27952809
rest->verticalClearance().setLocked(true);
27962810
bool isWholeOrHalf = rest->isWholeRest() || rest->durationType() == DurationType::V_HALF;
27972811
bool outAboveStaff = restAbove && restShape.bottom() + margin < minRestToChordClearance;

src/engraving/libmscore/utils.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "page.h"
3636
#include "part.h"
3737
#include "pitchspelling.h"
38+
#include "rest.h"
3839
#include "score.h"
3940
#include "segment.h"
4041
#include "sig.h"
@@ -1226,4 +1227,51 @@ void collectChordsAndRest(Segment* segment, staff_idx_t staffIdx, std::vector<Ch
12261227
}
12271228
}
12281229
}
1230+
1231+
void collectChordsOverlappingRests(Segment* segment, staff_idx_t staffIdx, std::vector<Chord*>& chords)
1232+
{
1233+
// Check if previous segments contain chords in other voices
1234+
// whose duration overlaps with rests on this segment
1235+
1236+
track_idx_t startTrack = staffIdx * VOICES;
1237+
track_idx_t endTrack = startTrack + VOICES;
1238+
1239+
std::set<track_idx_t> tracksToCheck;
1240+
for (track_idx_t track = startTrack; track < endTrack; ++track) {
1241+
EngravingItem* item = segment->elementAt(track);
1242+
if (!item || !item->isRest()) {
1243+
tracksToCheck.insert(track);
1244+
}
1245+
}
1246+
1247+
Fraction curTick = segment->rtick();
1248+
for (Segment* prevSeg = segment->prev(); prevSeg; prevSeg = prevSeg->prev()) {
1249+
if (!prevSeg->isChordRestType()) {
1250+
continue;
1251+
}
1252+
Fraction prevSegTick = prevSeg->rtick();
1253+
for (track_idx_t track : tracksToCheck) {
1254+
EngravingItem* e = prevSeg->elementAt(track);
1255+
if (!e || !e->isChord()) {
1256+
continue;
1257+
}
1258+
Chord* chord = toChord(e);
1259+
Fraction chordEndTick = prevSegTick + chord->actualTicks();
1260+
if (chordEndTick <= curTick) {
1261+
continue;
1262+
}
1263+
Measure* measure = segment->measure();
1264+
Segment* endSegment = measure->findSegmentR(SegmentType::ChordRest, chordEndTick);
1265+
if (!endSegment) {
1266+
continue;
1267+
}
1268+
EngravingItem* endItem = endSegment->elementAt(track);
1269+
if (!endItem || !endItem->isChord()) {
1270+
continue;
1271+
}
1272+
1273+
chords.push_back(chord);
1274+
}
1275+
}
1276+
}
12291277
}

src/engraving/libmscore/utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ extern bool allowRemoveWhenRemovingStaves(EngravingItem* item, staff_idx_t start
8686
extern bool moveDownWhenAddingStaves(EngravingItem* item, staff_idx_t startStaff, staff_idx_t endStaff = 0);
8787

8888
extern void collectChordsAndRest(Segment* segment, staff_idx_t staffIdx, std::vector<Chord*>& chords, std::vector<Rest*>& rests);
89+
extern void collectChordsOverlappingRests(Segment* segment, staff_idx_t staffIdx, std::vector<Chord*>& chords);
8990

9091
extern Interval ornamentIntervalToGeneralInterval(OrnamentInterval interval);
9192
} // namespace mu::engraving

vtest/scores/rests-5.mscz

16.3 KB
Binary file not shown.

0 commit comments

Comments
 (0)