Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions src/importexport/musicxml/internal/export/exportmusicxml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1840,7 +1840,11 @@ void ExportMusicXml::barlineLeft(const Measure* const m, const track_idx_t track
ending(m_xml, volta, true);
}
if (rs) {
m_xml.tag("repeat", { { "direction", "forward" } });
XmlWriter::Attributes attrs = { { "direction", "forward" } };
if (m_score->style().styleB(Sid::repeatBarTips)) {
attrs.push_back({ "winged", "curved" });
}
m_xml.tag("repeat", attrs);
}
m_xml.endElement();
}
Expand Down Expand Up @@ -2109,11 +2113,14 @@ void ExportMusicXml::barlineRight(const Measure* const m, const track_idx_t stra
}

if (bst == BarLineType::END_REPEAT || bst == BarLineType::END_START_REPEAT) {
XmlWriter::Attributes attrs = { { "direction", "backward" } };
if (m->repeatCount() > 2) {
m_xml.tag("repeat", { { "direction", "backward" }, { "times", m->repeatCount() } });
} else {
m_xml.tag("repeat", { { "direction", "backward" } });
attrs.push_back({ "times", m->repeatCount() });
}
if (m_score->style().styleB(Sid::repeatBarTips)) {
attrs.push_back({ "winged", "curved" });
}
m_xml.tag("repeat", attrs);
}

m_xml.endElement();
Expand Down
88 changes: 72 additions & 16 deletions src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5743,42 +5743,90 @@ Regular barlines should not be added at the start or end of a measure, as that c

void MusicXmlParserPass2::barline(const String& partId, Measure* measure, const Fraction& tick)
{
String loc = m_e.attribute("location");
AsciiStringView loc = m_e.asciiAttribute("location");
if (loc.empty()) {
loc = u"right";
loc = "right";
}
// Place barline in correct place
Fraction locTick = tick;
if (loc == u"left") {
if (loc == "left") {
locTick = measure->tick();
} else if (loc == u"right") {
} else if (loc == "right") {
locTick = measure->endTick();
}

const String codaLabel = m_e.attribute("coda");
const String segnoLabel = m_e.attribute("segno");

String barStyle;
Color barlineColor;
String endingNumber;
String endingType;
Color endingColor;
String endingText;
String repeat;
String count;
bool printEnding = true;

while (m_e.readNextStartElement()) {
if (m_e.name() == "bar-style") {
barlineColor = Color::fromString(m_e.asciiAttribute("color").ascii());
barStyle = m_e.readText();
} else if (m_e.name() == "ending") {
endingNumber = m_e.attribute("number");
endingType = m_e.attribute("type");
endingColor = Color::fromString(m_e.asciiAttribute("color").ascii());
printEnding = m_e.asciiAttribute("print-object") != "no";
endingText = m_e.readText();
} else if (m_e.name() == "segno") {
const Color segnoColor = Color::fromString(m_e.asciiAttribute("color").ascii());
const AsciiStringView segnoSymbol = m_e.asciiAttribute("smufl");
Measure* markedMeasure = (loc == "right") ? measure->nextMeasure() : measure;
if (markedMeasure == nullptr) {
m_logger->logError(u"coda or segno marker cannot be placed at the end of the score", &m_e);
m_e.skipCurrentElement();
continue;
}
Marker* m = Factory::createMarker(markedMeasure);
m->setMarkerType(MarkerType::SEGNO);
if (!segnoSymbol.empty()) {
m->setXmlText(u"<sym>" + String::fromAscii(segnoSymbol.ascii()) + u"</sym>");
}
if (!segnoLabel.empty()) {
m->setLabel(segnoLabel);
}
if (segnoColor.isValid()) {
colorItem(m, segnoColor);
}
const track_idx_t track = m_pass1.trackForPart(partId);
addElemOffset(m, track, u"above", markedMeasure, markedMeasure->tick());
m_e.skipCurrentElement();
} else if (m_e.name() == "coda") {
const Color codaColor = Color::fromString(m_e.asciiAttribute("color").ascii());
const AsciiStringView codaSymbol = m_e.asciiAttribute("smufl");
Measure* markedMeasure = (loc == "right") ? measure->nextMeasure() : measure;
if (markedMeasure == nullptr) {
m_logger->logError(u"coda or segno marker cannot be placed at the end of the score", &m_e);
m_e.skipCurrentElement();
continue;
}
Marker* m = Factory::createMarker(markedMeasure);
m->setMarkerType(MarkerType::CODA);
if (!codaSymbol.empty()) {
m->setXmlText(u"<sym>" + String::fromAscii(codaSymbol.ascii()) + u"</sym>");
}
if (!codaLabel.empty()) {
m->setLabel(codaLabel);
}
if (codaColor.isValid()) {
colorItem(m, codaColor);
}
const track_idx_t track = m_pass1.trackForPart(partId);
addElemOffset(m, track, u"above", markedMeasure, markedMeasure->tick());
m_e.skipCurrentElement();
} else if (m_e.name() == "fermata") {
const Color fermataColor = Color::fromString(m_e.asciiAttribute("color").ascii());
const String fermataType = m_e.attribute("type");
Segment* const segment = measure->getSegment(SegmentType::EndBarLine, locTick);
SegmentType st = SegmentType::BarLine;
if (locTick == measure->endTick()) {
st = SegmentType::EndBarLine;
} else if (locTick == measure->tick()) {
st = SegmentType::BeginBarLine;
}
Segment* const segment = measure->getSegment(st, locTick);
const track_idx_t track = m_pass1.trackForPart(partId);
Fermata* fermata = Factory::createFermata(segment);
fermata->setSymId(convertFermataToSymId(m_e.readText()));
Expand All @@ -5795,13 +5843,21 @@ void MusicXmlParserPass2::barline(const String& partId, Measure* measure, const
// Terminate tempo lines
const InferredTempoLineStack& lines = getInferredTempoLine();
terminateInferredLine(std::vector<TextLineBase*>(lines.begin(), lines.end()), locTick, track);
} else if (m_e.name() == "ending") {
endingNumber = m_e.attribute("number");
endingType = m_e.attribute("type");
endingColor = Color::fromString(m_e.asciiAttribute("color").ascii());
printEnding = m_e.asciiAttribute("print-object") != "no";
endingText = m_e.readText();
} else if (m_e.name() == "repeat") {
repeat = m_e.attribute("direction");
count = m_e.attribute("times");
if (count.empty()) {
count = u"2";
int count = m_e.attribute("times").toInt();
if (!count) {
count = 2;
}
measure->setRepeatCount(count.toInt());
measure->setRepeatCount(count);
bool repeatBarTips = !m_e.attribute("winged").empty() && m_e.attribute("winged") != "none";
m_score->undoChangeStyleVal(Sid::repeatBarTips, repeatBarTips);
m_e.skipCurrentElement();
} else {
skipLogCurrElem();
Expand Down
197 changes: 197 additions & 0 deletions src/importexport/musicxml/tests/data/testBarlineTips.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 4.0 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
<score-partwise version="4.0">
<work>
<work-title>Repeats on wings</work-title>
</work>
<identification>
<encoding>
<software>MuseScore 0.7.0</software>
<encoding-date>2007-09-10</encoding-date>
<supports element="accidental" type="yes"/>
<supports element="beam" type="yes"/>
<supports element="print" attribute="new-page" type="no"/>
<supports element="print" attribute="new-system" type="no"/>
<supports element="stem" type="yes"/>
</encoding>
</identification>
<part-list>
<score-part id="P1">
<part-name print-object="no">Piano</part-name>
<score-instrument id="P1-I1">
<instrument-name>Piano</instrument-name>
</score-instrument>
<midi-device id="P1-I1" port="1"></midi-device>
<midi-instrument id="P1-I1">
<midi-channel>1</midi-channel>
<midi-program>1</midi-program>
<volume>78.7402</volume>
<pan>0</pan>
</midi-instrument>
</score-part>
</part-list>
<part id="P1">
<measure number="1">
<attributes>
<divisions>1</divisions>
<key>
<fifths>0</fifths>
</key>
<time>
<beats>4</beats>
<beat-type>4</beat-type>
</time>
<staves>2</staves>
<clef number="1">
<sign>G</sign>
<line>2</line>
</clef>
<clef number="2">
<sign>F</sign>
<line>4</line>
</clef>
</attributes>
<note>
<rest measure="yes"/>
<duration>4</duration>
<voice>1</voice>
<staff>1</staff>
</note>
<backup>
<duration>4</duration>
</backup>
<note>
<pitch>
<step>C</step>
<octave>3</octave>
</pitch>
<duration>2</duration>
<voice>5</voice>
<type>half</type>
<stem>up</stem>
<staff>2</staff>
</note>
<note>
<pitch>
<step>A</step>
<octave>3</octave>
</pitch>
<duration>2</duration>
<voice>5</voice>
<type>half</type>
<stem>down</stem>
<staff>2</staff>
</note>
</measure>
<measure number="2">
<barline location="left">
<bar-style>heavy-light</bar-style>
<repeat direction="forward" winged="curved"/>
</barline>
<note>
<rest measure="yes"/>
<duration>4</duration>
<voice>1</voice>
<staff>1</staff>
</note>
<backup>
<duration>4</duration>
</backup>
<note>
<pitch>
<step>G</step>
<octave>3</octave>
</pitch>
<duration>2</duration>
<voice>5</voice>
<type>half</type>
<stem>down</stem>
<staff>2</staff>
</note>
<note>
<pitch>
<step>G</step>
<octave>2</octave>
</pitch>
<duration>2</duration>
<voice>5</voice>
<type>half</type>
<stem>up</stem>
<staff>2</staff>
</note>
</measure>
<measure number="3">
<note>
<rest measure="yes"/>
<duration>4</duration>
<voice>1</voice>
<staff>1</staff>
</note>
<backup>
<duration>4</duration>
</backup>
<note>
<pitch>
<step>C</step>
<octave>3</octave>
</pitch>
<duration>2</duration>
<voice>5</voice>
<type>half</type>
<stem>up</stem>
<staff>2</staff>
</note>
<note>
<pitch>
<step>E</step>
<octave>3</octave>
</pitch>
<duration>2</duration>
<voice>5</voice>
<type>half</type>
<stem>down</stem>
<staff>2</staff>
</note>
<barline location="right">
<bar-style>light-heavy</bar-style>
<repeat direction="backward" times="4" winged="curved"/>
</barline>
</measure>
<measure number="4">
<note>
<rest measure="yes"/>
<duration>4</duration>
<voice>1</voice>
<staff>1</staff>
</note>
<backup>
<duration>4</duration>
</backup>
<note>
<pitch>
<step>F</step>
<octave>3</octave>
</pitch>
<duration>2</duration>
<voice>5</voice>
<type>half</type>
<stem>down</stem>
<staff>2</staff>
</note>
<note>
<pitch>
<step>C</step>
<octave>3</octave>
</pitch>
<duration>2</duration>
<voice>5</voice>
<type>half</type>
<stem>up</stem>
<staff>2</staff>
</note>
<barline location="right">
<bar-style>light-heavy</bar-style>
</barline>
</measure>
</part>
</score-partwise>
7 changes: 5 additions & 2 deletions src/importexport/musicxml/tests/musicxml_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,9 @@ TEST_F(MusicXml_Tests, articulationCombination) {
TEST_F(MusicXml_Tests, backupRoundingError) {
musicXmlImportTestRef("testBackupRoundingError");
}
TEST_F(MusicXml_Tests, barlineFermatas) {
musicXmlIoTest("testBarlineFermatas");
}
TEST_F(MusicXml_Tests, barlineLoc) {
musicXmlImportTestRef("testBarlineLoc");
}
Expand All @@ -405,8 +408,8 @@ TEST_F(MusicXml_Tests, noteflightStartRepeatBarline) {
TEST_F(MusicXml_Tests, barlineSpan) {
musicXmlIoTest("testBarlineSpan");
}
TEST_F(MusicXml_Tests, barlineFermatas) {
musicXmlIoTest("testBarlineFermatas");
TEST_F(MusicXml_Tests, barlineTips) {
musicXmlIoTest("testBarlineTips");
}
TEST_F(MusicXml_Tests, barStyles) {
musicXmlIoTest("testBarStyles");
Expand Down
Loading