Skip to content

Commit 833b6a8

Browse files
iveshenry18Jojo-Schmitz
authored andcommitted
ENG-25: Bolster placement defaults
This commit adds some context-aware placement defaults for text and dynamics (in the case that neither "placement" nor "default-y" nor "relative-y" are specified). Namely, both expression text and dynamics are placed below the staff unless it is a vocal staff. To this end, there are some simple checks added to discern whether a part is a vocal part, which is currently a simple check against the name of the staff and a check for the presence of lyrics. Additionally, the "expression text" is currently defined by the presence of italics in the _wordsText, and an absence of _tempoText. Duplicate of musescore#8325, plus fixing a compiler warning, see musescore#8554
1 parent 1dd22aa commit 833b6a8

File tree

9 files changed

+1173
-5
lines changed

9 files changed

+1173
-5
lines changed

importexport/musicxml/importmxmlpass1.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3216,6 +3216,7 @@ void MusicXMLParserPass1::note(const QString& partId,
32163216
else if (_e.name() == "lyric") {
32173217
const auto number = _e.attributes().value("number").toString();
32183218
_parts[partId].lyricNumberHandler().addNumber(number);
3219+
_parts[partId].hasLyrics(true);
32193220
_e.skipCurrentElement();
32203221
}
32213222
else if (_e.name() == "notations")

importexport/musicxml/importmxmlpass1.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ class MusicXMLParserPass1 {
166166
int octaveShift(const QString& id, const int staff, const Fraction f) const;
167167
const CreditWordsList& credits() const { return _credits; }
168168
bool hasBeamingInfo() const { return _hasBeamingInfo; }
169+
bool isVocalStaff(const QString& id) const { return _parts[id].isVocalStaff(); }
169170
static VBox* createAndAddVBoxForCreditWords(Score* const score, const int miny = 0, const int maxy = 75);
170171
QString supportsTranspose() const { return _supportsTranspose; }
171172
void addInferredTranspose(const QString& partId);

importexport/musicxml/importmxmlpass2.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -859,8 +859,11 @@ static void addElemOffset(Element* el, int track, const QString& placement, Meas
859859
el->setPlacement(placement == "above" ? Placement::ABOVE : Placement::BELOW);
860860
}
861861
#endif
862-
el->setPlacement(placement == "above" ? Placement::ABOVE : Placement::BELOW);
863-
el->setPropertyFlags(Pid::PLACEMENT, PropertyFlags::UNSTYLED);
862+
if (placement != "") {
863+
el->setPlacement(placement == "above" ? Placement::ABOVE : Placement::BELOW);
864+
el->setPropertyFlags(Pid::PLACEMENT, PropertyFlags::UNSTYLED);
865+
}
866+
864867

865868
el->setTrack(el->isTempoText() ? 0 : track); // TempoText must be in track 0
866869
Segment* s = measure->getSegment(SegmentType::ChordRest, tick);
@@ -2490,6 +2493,8 @@ void MusicXMLParserDirection::direction(const QString& partId,
24902493

24912494
_placement = _e.attributes().value("placement").toString();
24922495
int track = _pass1.trackForPart(partId);
2496+
bool isVocalStaff = _pass1.isVocalStaff(partId);
2497+
bool isExpressionText = false;
24932498
//qDebug("direction track %d", track);
24942499
QList<MusicXmlSpannerDesc> starts;
24952500
QList<MusicXmlSpannerDesc> stops;
@@ -2574,6 +2579,7 @@ void MusicXMLParserDirection::direction(const QString& partId,
25742579
if (_wordsText != "" || _metroText != "") {
25752580
t = new StaffText(_score);
25762581
t->setXmlText(_wordsText + _metroText);
2582+
isExpressionText = _wordsText.contains("<i>") && _metroText.isEmpty();
25772583
}
25782584
else {
25792585
t = new RehearsalMark(_score);
@@ -2598,10 +2604,17 @@ void MusicXMLParserDirection::direction(const QString& partId,
25982604
t->setFrameType(FrameType::SQUARE);
25992605
t->setFrameRound(0);
26002606
}
2607+
2608+
QString wordsPlacement = placement();
2609+
// Case-based defaults
2610+
if (wordsPlacement.isEmpty()) {
2611+
if (isVocalStaff) wordsPlacement = "above";
2612+
else if (isExpressionText) wordsPlacement = "below";
2613+
}
26012614

26022615
if (isLikelyFingering()) {
26032616
_logger->logDebugInfo(QString("Inferring fingering: %1").arg(_wordsText));
2604-
MusicXMLInferredFingering* inferredFingering = new MusicXMLInferredFingering(totalY(), t, _wordsText, track, placement(), measure, tick + _offset);
2617+
MusicXMLInferredFingering* inferredFingering = new MusicXMLInferredFingering(totalY(), t, _wordsText, track, wordsPlacement, measure, tick + _offset);
26052618
inferredFingerings.push_back(inferredFingering);
26062619
}
26072620
else if (directionToDynamic()) {
@@ -2610,7 +2623,7 @@ void MusicXMLParserDirection::direction(const QString& partId,
26102623
else {
26112624
// Add element to score later, after collecting all the others and sorting by default-y
26122625
// This allows default-y to be at least respected by the order of elements
2613-
MusicXMLDelayedDirectionElement* delayedDirection = new MusicXMLDelayedDirectionElement(hasTotalY() ? totalY() : 100, t, track, placement(), measure, tick + _offset);
2626+
MusicXMLDelayedDirectionElement* delayedDirection = new MusicXMLDelayedDirectionElement(hasTotalY() ? totalY() : 100, t, track, wordsPlacement, measure, tick + _offset);
26142627
delayedDirections.push_back(delayedDirection);
26152628
}
26162629
}
@@ -2650,9 +2663,14 @@ void MusicXMLParserDirection::direction(const QString& partId,
26502663
dyn->setVelocity( dynaValue );
26512664
}
26522665

2666+
QString dynamicsPlacement = placement();
2667+
// Case-based defaults
2668+
if (dynamicsPlacement.isEmpty())
2669+
dynamicsPlacement = isVocalStaff ? "above" : "below";
2670+
26532671
// Add element to score later, after collecting all the others and sorting by default-y
26542672
// This allows default-y to be at least respected by the order of elements
2655-
MusicXMLDelayedDirectionElement* delayedDirection = new MusicXMLDelayedDirectionElement(hasTotalY() ? totalY() : 100, dyn, track, placement(), measure, tick + _offset);
2673+
MusicXMLDelayedDirectionElement* delayedDirection = new MusicXMLDelayedDirectionElement(hasTotalY() ? totalY() : 100, dyn, track, dynamicsPlacement, measure, tick + _offset);
26562674
delayedDirections.push_back(delayedDirection);
26572675
}
26582676

importexport/musicxml/importxmlfirstpass.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ namespace Ms {
1616

1717
// TODO: move somewhere else
1818

19+
static const std::vector<QString> vocalInstrumentNames({"Voice",
20+
"Soprano",
21+
"Mezzo-Soprano",
22+
"Alto",
23+
"Tenor",
24+
"Baritone",
25+
"Bass",
26+
"Women",
27+
"Men"});
28+
1929
MusicXmlPart::MusicXmlPart(QString id, QString name)
2030
: id(id), name(name)
2131
{
@@ -92,6 +102,12 @@ void MusicXmlPart::calcOctaveShifts()
92102
}
93103
}
94104

105+
bool MusicXmlPart::isVocalStaff() const
106+
{
107+
return (std::find(vocalInstrumentNames.begin(), vocalInstrumentNames.end(), name) != vocalInstrumentNames.end()
108+
|| _hasLyrics);
109+
}
110+
95111
//---------------------------------------------------------
96112
// interval
97113
//---------------------------------------------------------

importexport/musicxml/importxmlfirstpass.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ class MusicXmlPart {
8484
const LyricNumberHandler& lyricNumberHandler() const { return _lyricNumberHandler; }
8585
void setMaxStaff(const int staff);
8686
int maxStaff() const { return _maxStaff; }
87+
bool isVocalStaff() const;
88+
void hasLyrics(bool b) { _hasLyrics = b; }
8789
private:
8890
QString id;
8991
QString name;
@@ -96,6 +98,7 @@ class MusicXmlPart {
9698
QVector<MusicXmlOctaveShiftList> octaveShifts; // octave shift list for every staff
9799
LyricNumberHandler _lyricNumberHandler;
98100
int _maxStaff = 0; // maximum staff value found (1 based), 0 = none
101+
bool _hasLyrics = false;
99102
};
100103

101104
} // namespace Ms
43.9 KB
Binary file not shown.

0 commit comments

Comments
 (0)