Skip to content

Commit

Permalink
ENG-55: Combine staff text with tempo text
Browse files Browse the repository at this point in the history
Sometimes tempo text with additional instructions is exported as two
separate directions. Previously, this was imported as a Tempo Text
element and a separate Staff Text element. This commit adds a function
to infer these cases and merge the text from the Staff Text element
into the Tempo Text.

Duplicate of musescore#8412, part 2
  • Loading branch information
iveshenry18 authored and Jojo-Schmitz committed Sep 23, 2021
1 parent 594d2e1 commit 01d2310
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 896 deletions.
38 changes: 27 additions & 11 deletions importexport/musicxml/importmxmlpass2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2326,7 +2326,7 @@ void MusicXMLParserPass2::measure(const QString& partId,
}

// Sort and add delayed directions
// delayedDirections.combineTempoText();
delayedDirections.combineTempoText();
std::sort(delayedDirections.begin(), delayedDirections.end(),
// Lambda: sort by absolute value of totalY
[](const MusicXMLDelayedDirectionElement* a, const MusicXMLDelayedDirectionElement* b) -> bool {
Expand Down Expand Up @@ -2602,6 +2602,16 @@ static void preventNegativeTick(const Fraction& tick, Fraction& offset, MxmlLogg
}
}

//---------------------------------------------------------
// isTempoOrphanCandidate
//---------------------------------------------------------

bool MusicXMLDelayedDirectionElement::isTempoOrphanCandidate() const
{
return _element->isStaffText()
&& _placement == "above"
&& toStaffText(_element)->xmlText().contains("<b>");
}

//---------------------------------------------------------
// addElem
Expand All @@ -2624,22 +2634,28 @@ QString MusicXMLParserDirection::placement() const
//---------------------------------------------------------
/**
Combine potentially separated tempo text.
TODO: Use flags (hasTempoCandidate, etc.) to make more efficient
*/

void DelayedDirectionsList::combineTempoText()
{
// Iterate through each distinct pair (backwards, to allow for deletions)
// Iterate through candidates
for (auto ddi1 = rbegin(), ddi1Next = ddi1; ddi1 != rend(); ddi1 = ddi1Next) {
ddi1Next = std::next(ddi1);
if (false)
continue;
for (auto ddi2 = ddi1 + 1, ddi2Next = ddi1; ddi2 != rend(); ddi2 = ddi2Next) {
ddi2Next = std::next(ddi2);
// Combine and remove articulations if present in map
if (false) {
ddi1Next = decltype(ddi1){ erase(std::next(ddi1).base()) };
ddi2Next = decltype(ddi2){ erase(std::next(ddi2).base()) };
if ((*ddi1)->isTempoOrphanCandidate()) {
for (auto ddi2 = rbegin(), ddi2Next = ddi2; ddi2 != rend(); ddi2 = ddi2Next) {
ddi2Next = std::next(ddi2);
// Combine with tempo text if present
if (ddi1 != ddi2
&& (*ddi2)->tick() == (*ddi1)->tick()
&& (*ddi2)->element()->isTempoText()) {
TempoText* tt = toTempoText((*ddi2)->element());
StaffText* st = toStaffText((*ddi1)->element());
QString sep = tt->plainText().endsWith(' ') || st->plainText().startsWith(' ') ? "" : " ";
tt->setXmlText(tt->xmlText() + sep + st->xmlText());
delete st;
ddi1Next = decltype(ddi1){ erase(std::next(ddi1).base()) };
break;
}
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion importexport/musicxml/importmxmlpass2.h
Original file line number Diff line number Diff line change
Expand Up @@ -430,8 +430,13 @@ class MusicXMLDelayedDirectionElement {
QString placement, Measure* measure, Fraction tick) :
_totalY(totalY), _element(element), _track(track), _placement(placement),
_measure(measure), _tick(tick) {}
void addElem();

qreal totalY() const { return _totalY; }
Element* element() { return _element; }
Fraction tick() const { return _tick; }

void addElem();
bool isTempoOrphanCandidate() const;

private:
qreal _totalY;
Expand Down

0 comments on commit 01d2310

Please sign in to comment.