Skip to content

Commit

Permalink
fix #20912
Browse files Browse the repository at this point in the history
  • Loading branch information
lvinken committed May 6, 2013
1 parent 83ea471 commit 53cc666
Show file tree
Hide file tree
Showing 6 changed files with 280 additions and 27 deletions.
96 changes: 72 additions & 24 deletions mscore/capella.cpp
Expand Up @@ -45,6 +45,7 @@
#include "libmscore/layoutbreak.h"
#include "libmscore/dynamic.h"
#include "libmscore/barline.h"
#include "libmscore/volta.h"

//---------------------------------------------------------
// errmsg
Expand Down Expand Up @@ -237,6 +238,44 @@ static void processBasicDrawObj(QList<BasicDrawObj*> objects, Segment* s, int tr
}
}

//---------------------------------------------------------
// findChordRests -- find begin and end ChordRest for BasicDrawObj o
// return true on success (both begin and end found)
//---------------------------------------------------------

static bool findChordRests(BasicDrawObj const* const o, Score const* const score, const int track, const int tick,
ChordRest*& cr1, ChordRest*& cr2)
{
cr1 = 0; // ChordRest where BasicDrawObj o begins
cr2 = 0; // ChordRest where BasicDrawObj o ends

// find the ChordRests where o begins and ends
int n = o->nNotes + 1; // # notes in BasicDrawObj (nNotes is # notes following the first note)
for (Segment* seg = score->tick2segment(tick); seg; seg = seg->next1()) {
if (seg->segmentType() != Segment::SegChordRest)
continue;
ChordRest* cr = static_cast<ChordRest*>(seg->element(track));
if (cr) {
--n; // found a ChordRest, count down
if (!cr1) cr1 = cr; // found first ChordRest
}
else
qDebug(" %d empty seg", n);
if (n == 0) {
cr2 = cr; // cr should be the second ChordRest
break;
}
}
qDebug("findChordRests o %p nNotes %d score %p track %d tick %d cr1 %p cr2 %p", o, o->nNotes, score, track, tick, cr1, cr2);

if (!(cr1 && cr2)) {
qDebug("first or second anchor for BasicDrawObj not found (tick %d type %d track %d first %p second %p)",
tick, o->type, track, cr1, cr2);
return false;
}
return true;
}

//---------------------------------------------------------
// readCapVoice
//---------------------------------------------------------
Expand Down Expand Up @@ -646,34 +685,17 @@ static int readCapVoice(Score* score, CapVoice* cvoice, int staffIdx, int tick,
break;
case CAP_SLUR:
{
SlurObj* so = static_cast<SlurObj*>(o);
// SlurObj* so = static_cast<SlurObj*>(o);
// qDebug("slur tick %d %d-%d-%d-%d %d-%d", tick, so->nEnd, so->nMid,
// so->nDotDist, so->nDotWidth, so->nRefNote, so->nNotes);
ChordRest* cr1 = 0; // ChordRest where slur begins
ChordRest* cr2 = 0; // ChordRest where slur ends
bool res = findChordRests(o, score, track, tick, cr1, cr2);

// find the ChordRests where the slur begins and ends
int n = so->nNotes + 1; // # notes in slur (nNotes is # notes following the first note)
for (Segment* seg = score->tick2segment(tick); seg; seg = seg->next1()) {
if (seg->segmentType() != Segment::SegChordRest)
continue;
ChordRest* cr = static_cast<ChordRest*>(seg->element(track));
if (cr) {
--n; // found a ChordRest, count down
if (!cr1) cr1 = cr; // found first ChordRest
}
else
qDebug(" %d empty seg", n);
if (n == 0) {
cr2 = cr; // cr should be the second ChordRest
break;
}
}
// qDebug("cr1 %p cr2 %p", cr1, cr2);

if (cr1 && cr2) {
if (res) {
if (cr1 == cr2)
qDebug("first and second anchor for slur identical (tick %d track %d first %p second %p)", tick, track, cr1, cr2);
qDebug("first and second anchor for slur identical (tick %d track %d first %p second %p)",
tick, track, cr1, cr2);
else {
Slur* slur = new Slur(score);
qDebug("tick %d track %d cr1 %p cr2 %p -> slur %p", tick, track, cr1, cr2, slur);
Expand All @@ -683,8 +705,6 @@ static int readCapVoice(Score* score, CapVoice* cvoice, int staffIdx, int tick,
slur->setEndElement(cr2);
}
}
else
qDebug("first or second anchor for slur not found (tick %d track %d first %p second %p)", tick, track, cr1, cr2);
}
break;
case CAP_TEXT: {
Expand All @@ -707,6 +727,30 @@ static int readCapVoice(Score* score, CapVoice* cvoice, int staffIdx, int tick,
measure->add(s);
}
break;
case CAP_VOLTA:
{
VoltaObj* vo = static_cast<VoltaObj*>(o);
ChordRest* cr1 = 0; // ChordRest where volta begins
ChordRest* cr2 = 0; // ChordRest where volta ends
bool res = findChordRests(o, score, track, tick, cr1, cr2);

if (res) {
Volta* volta = new Volta(score);
volta->setTrack(track);
// TODO also support endings such as "1 - 3"
volta->setText(QString("%1.").arg(vo->to));
volta->endings().append(vo->to);
if (vo->bRight)
volta->setVoltaType(VoltaType::CLOSED);
else
volta->setVoltaType(VoltaType::OPEN);
volta->setStartElement(cr1->measure());
cr1->measure()->add(volta);
volta->setEndElement(cr2->measure());
cr2->measure()->addSpannerBack(volta);
}
}
break;
default:
break;
}
Expand Down Expand Up @@ -1200,6 +1244,8 @@ void VoltaObj::read()
unsigned char numbers = cap->readByte();
from = numbers & 0x0F;
to = (numbers >> 4) & 0x0F;
qDebug("VoltaObj::read x0 %d x1 %d y %d bLeft %d bRight %d bDotted %d allNumbers %d from %d to %d",
x0, x1, y, bLeft, bRight, bDotted, allNumbers, from, to);
}

//---------------------------------------------------------
Expand Down Expand Up @@ -1364,6 +1410,8 @@ void BasicDrawObj::read()
nNotes = range & 0x0fff;
background = range & 0x1000;
pageRange = (range >> 13) & 0x7;
qDebug("BasicDrawObj::read modeX %d modeY %d distY %d flags %d nRefNote %d nNotes %d background %d pageRange %d",
modeX, modeY, distY, flags, nRefNote, nNotes, background, pageRange);
}

//---------------------------------------------------------
Expand Down
6 changes: 5 additions & 1 deletion mscore/capella.h
Expand Up @@ -383,8 +383,12 @@ class NotelinesObj : public BasicDrawObj {

class VoltaObj : public BasicDrawObj {
public:
VoltaObj(Capella* c) : BasicDrawObj(CAP_VOLTA, c) {}
VoltaObj(Capella* c)
: BasicDrawObj(CAP_VOLTA, c), x0(0), x1(0), y(0),
bLeft(false), bRight(false), bDotted(false),
allNumbers(false), from(0), to(0) {}
void read();
void readCapx(XmlReader& e);

int x0, x1, y;
QColor color;
Expand Down
35 changes: 33 additions & 2 deletions mscore/capxml.cpp
Expand Up @@ -463,6 +463,34 @@ void SlurObj::readCapx(XmlReader& e)
e.skipCurrentElement();
}

//---------------------------------------------------------
// VoltaObj::readCapx -- capx equivalent of VoltaObj::read
//---------------------------------------------------------

void VoltaObj::readCapx(XmlReader& e)
{
bLeft = e.attribute("leftBent", "true") == "true";
bRight = e.attribute("rightBent", "true") == "true";
bDotted = e.attribute("dotted", "false") == "true";
allNumbers = e.attribute("allNumbers", "false") == "true";
int firstNumber = e.intAttribute("firstNumber", 0);
int lastNumber = e.intAttribute("lastNumber", 0);
if (firstNumber == 0) {
// don't know what this means (spec: no number)
// cap status equivalent to no first or last number
from = 1;
to = 0;
}
else {
from = firstNumber;
to = (lastNumber == 0) ? firstNumber : lastNumber;
}
qDebug("VoltaObj::read firstNumber %d lastNumber %d", firstNumber, lastNumber);
qDebug("VoltaObj::read x0 %d x1 %d y %d bLeft %d bRight %d bDotted %d allNumbers %d from %d to %d",
x0, x1, y, bLeft, bRight, bDotted, allNumbers, from, to);
e.readNext();
}

//---------------------------------------------------------
// readCapxDrawObjectArray -- capx equivalent of readDrawObjectArray()
//---------------------------------------------------------
Expand All @@ -476,6 +504,7 @@ QList<BasicDrawObj*> Capella::readCapxDrawObjectArray(XmlReader& e)
while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
if (tag == "basic") {
// note: the <basic> element always follows the DrawObject it applies to
if (bdo)
bdo->readCapx(e);
else
Expand Down Expand Up @@ -538,8 +567,10 @@ QList<BasicDrawObj*> Capella::readCapxDrawObjectArray(XmlReader& e)
e.skipCurrentElement();
}
else if (tag == "volta") {
qDebug("readCapxDrawObjectArray: found volta (skipping)");
e.skipCurrentElement();
VoltaObj* o = new VoltaObj(this);
bdo = o; // save o to handle the "basic" tag (which sometimes follows)
o->readCapx(e);
ol.append(o);
}
else if (tag == "trill") {
qDebug("readCapxDrawObjectArray: found trill (skipping)");
Expand Down
Binary file added mtest/capella/io/testVolta1.capx
Binary file not shown.
169 changes: 169 additions & 0 deletions mtest/capella/io/testVolta1.capx-ref.mscx
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<museScore version="1.24">
<Score>
<LayerTag id="0" tag="default"></LayerTag>
<currentLayer>0</currentLayer>
<Division>480</Division>
<Style>
<minSystemDistance>8</minSystemDistance>
<maxSystemDistance>12</maxSystemDistance>
<measureSpacing>1</measureSpacing>
<smallStaffMag>0.681818</smallStaffMag>
<page-layout>
<page-height>1683.78</page-height>
<page-width>1190.55</page-width>
<page-margins type="even">
<left-margin>56.6929</left-margin>
<right-margin>56.6929</right-margin>
<top-margin>56.6929</top-margin>
<bottom-margin>113.386</bottom-margin>
</page-margins>
<page-margins type="odd">
<left-margin>56.6929</left-margin>
<right-margin>56.6929</right-margin>
<top-margin>56.6929</top-margin>
<bottom-margin>113.386</bottom-margin>
</page-margins>
</page-layout>
<Spatium>1.76</Spatium>
</Style>
<showInvisible>1</showInvisible>
<showUnprintable>1</showUnprintable>
<showFrames>1</showFrames>
<showMargins>0</showMargins>
<metaTag name="copyright"></metaTag>
<metaTag name="movementNumber"></metaTag>
<metaTag name="movementTitle"></metaTag>
<metaTag name="source"></metaTag>
<metaTag name="workNumber"></metaTag>
<metaTag name="workTitle"></metaTag>
<PageList>
<Page>
<System>
</System>
<System>
</System>
</Page>
</PageList>
<Part>
<Staff id="1">
<type>0</type>
</Staff>
<trackName></trackName>
<Instrument>
<longName pos="0">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><!--StartFragment-->Guitar<!--EndFragment--></p></body></html>
</longName>
<shortName pos="0">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><!--StartFragment-->Gtr.<!--EndFragment--></p></body></html>
</shortName>
<trackName></trackName>
<Channel name="normal">
<program value="24"/>
</Channel>
</Instrument>
</Part>
<Staff id="1">
<VBox>
<height>14</height>
</VBox>
<Measure number="1">
<Clef>
<concertClefType>G8vb</concertClefType>
<transposingClefType>G8vb</transposingClefType>
</Clef>
<TimeSig>
<sigN>4</sigN>
<sigD>4</sigD>
<showCourtesySig>1</showCourtesySig>
</TimeSig>
<Text>
<pos x="14.2045" y="-8.52273"/>
<style></style>
<text>Volta 1</text>
</Text>
<Text>
<pos x="14.2045" y="-5.68182"/>
<style></style>
<text>MuseScore testfile</text>
</Text>
<Chord>
<durationType>whole</durationType>
<Note>
<pitch>55</pitch>
<tpc>15</tpc>
</Note>
</Chord>
</Measure>
<Measure number="2">
<endRepeat>2</endRepeat>
<Volta id="2">
<subtype>1</subtype>
<lineWidth>0.1</lineWidth>
<anchor>1</anchor>
<beginText>
<style>Volta</style>
<text>1.</text>
</beginText>
<endings>1</endings>
</Volta>
<endSpanner id="2"/>
<Chord>
<durationType>whole</durationType>
<Note>
<pitch>57</pitch>
<tpc>17</tpc>
</Note>
</Chord>
</Measure>
<Measure number="3">
<Volta id="3">
<subtype>0</subtype>
<lineWidth>0.1</lineWidth>
<anchor>1</anchor>
<beginText>
<style>Volta</style>
<text>2.</text>
</beginText>
<endings>2</endings>
</Volta>
<endSpanner id="3"/>
<Chord>
<durationType>whole</durationType>
<Note>
<pitch>59</pitch>
<tpc>19</tpc>
</Note>
</Chord>
</Measure>
<Measure number="4">
<LayoutBreak>
<subtype>line</subtype>
<pause>3</pause>
</LayoutBreak>
<Text>
<pos x="2.84091" y="-3.40909"/>
<style></style>
<text>Leon Vinken</text>
</Text>
<Chord>
<durationType>whole</durationType>
<Note>
<pitch>60</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<BarLine>
<subtype>end</subtype>
<span>1</span>
</BarLine>
</Measure>
</Staff>
</Score>
</museScore>
1 change: 1 addition & 0 deletions mtest/capella/io/tst_capella_io.cpp
Expand Up @@ -58,6 +58,7 @@ private slots:
void capxTestSlurTie() { capxReadTest("testSlurTie"); }
void capxTestText1() { capxReadTest("testText1"); }
// void capxTestTuplet1() { capxReadTest("testTuplet1"); } // generates different (incorrect ?) l1 and l2 values in beams
void capxTestVolta1() { capxReadTest("testVolta1"); }
};

//---------------------------------------------------------
Expand Down

0 comments on commit 53cc666

Please sign in to comment.