Skip to content

Commit

Permalink
prevent local ts crash and fix paste behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
miiizen committed Dec 1, 2023
1 parent 2b33488 commit 43ec891
Show file tree
Hide file tree
Showing 7 changed files with 476 additions and 10 deletions.
9 changes: 8 additions & 1 deletion src/engraving/dom/durationelement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,16 @@ float DurationElement::timeStretchFactor() const
// actualTicks
//---------------------------------------------------------

Fraction DurationElement::actualTicks(Fraction& tick) const
{
// Use when tick() is unreliable, for example when pasting
return globalTicks() / staff()->timeStretch(tick);
}

Fraction DurationElement::actualTicks() const
{
return globalTicks() / staff()->timeStretch(tick());
Fraction t(tick());
return actualTicks(t);
}

//---------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions src/engraving/dom/durationelement.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class DurationElement : public EngravingItem
Tuplet* topTuplet() const;
virtual Beam* beam() const { return nullptr; }

Fraction actualTicks(Fraction& tick) const;
Fraction actualTicks() const;

// Length expressed as a fraction of a whole note
Expand Down
18 changes: 10 additions & 8 deletions src/engraving/dom/paste.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "sig.h"
#include "staff.h"
#include "tie.h"
#include "timesig.h"
#include "tremolo.h"
#include "tuplet.h"
#include "undo.h"
Expand Down Expand Up @@ -124,7 +125,7 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t)
transposeChord(toChord(cr), tick);
if (toChord(cr)->tremolo() && toChord(cr)->tremolo()->twoNotes()) {
twoNoteTremoloFactor = 2;
} else if (cr->durationTypeTicks() == (cr->actualTicks() * 2)) {
} else if (cr->durationTypeTicks() == (cr->actualTicks(tick) * 2)) {
// this could be the 2nd note of a two-note tremolo
// check previous CR on same track, if it has a two-note tremolo, then set twoNoteTremoloFactor to 2
Segment* seg = measure->undoGetSegment(SegmentType::ChordRest, tick);
Expand Down Expand Up @@ -167,19 +168,19 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t)
if (cr->isMeasureRepeat()) {
partialCopy = toMeasureRepeat(cr)->actualTicks() != measure->ticks();
} else if (!isGrace && !cr->tuplet()) {
partialCopy = cr->durationTypeTicks() != (cr->actualTicks() * twoNoteTremoloFactor);
partialCopy = cr->durationTypeTicks() != (cr->actualTicks(tick) * twoNoteTremoloFactor);
}

// if note is too long to fit in measure, split it up with a tie across the barline
// exclude tuplets from consideration
// we have already disallowed a tuplet from crossing the barline, so there is no problem here
// but due to rounding, it might appear from actualTicks() that the last note is too long by a couple of ticks

if (!isGrace && !cr->tuplet() && (tick + cr->actualTicks() > measureEnd || partialCopy || convertMeasureRest)) {
if (!isGrace && !cr->tuplet() && (tick + cr->actualTicks(tick) > measureEnd || partialCopy || convertMeasureRest)) {
if (cr->isChord()) {
// split Chord
Chord* c = toChord(cr);
Fraction rest = c->actualTicks();
Fraction rest = c->actualTicks(tick);
bool firstpart = true;
while (rest.isNotZero()) {
measure = tick2measure(tick);
Expand All @@ -192,9 +193,10 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t)
std::vector<TDuration> dl = toRhythmicDurationList(len, false, tick - measure->tick(), sigmap()->timesig(
tick).nominal(), measure, MAX_DOTS);
TDuration d = dl[0];
Fraction c2Tick(tick + c->tick());
c2->setDurationType(d);
c2->setTicks(d.fraction());
rest -= c2->actualTicks();
rest -= c2->actualTicks(c2Tick);
undoAddCR(c2, measure, tick);

std::vector<Note*> nl1 = c->notes();
Expand All @@ -219,7 +221,7 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t)
}
c = c2;
firstpart = false;
tick += c->actualTicks();
tick += c->actualTicks(c2Tick);
}
} else if (cr->isRest()) {
// split Rest
Expand All @@ -239,7 +241,7 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t)
r2->setTicks(d.isMeasure() ? measure->ticks() : d.fraction());
undoAddCR(r2, measure, tick);
rest -= r2->ticks();
tick += r2->actualTicks();
tick += r2->actualTicks(tick);
firstpart = false;
}
} else if (cr->isMeasureRepeat()) {
Expand All @@ -260,7 +262,7 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t)
r2->setDurationType(d);
undoAddCR(r2, measure, tick);
rest -= d.fraction();
tick += r2->actualTicks();
tick += r2->actualTicks(tick);
}
delete r;
}
Expand Down
2 changes: 1 addition & 1 deletion src/engraving/rw/read410/read410.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ bool Read410::pasteStaff(XmlReader& e, Segment* dst, staff_idx_t dstStaff, Fract
if (tuplet) {
cr->readAddTuplet(tuplet);
}
ctx.incTick(cr->actualTicks());
ctx.incTick(cr->actualTicks(tick));
if (doScale) {
Fraction d = cr->durationTypeTicks();
cr->setTicks(cr->ticks() * scale);
Expand Down
234 changes: 234 additions & 0 deletions src/engraving/tests/copypaste_data/copypaste27-ref.mscx
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
<?xml version="1.0" encoding="UTF-8"?>
<museScore version="4.20">
<Score>
<Division>480</Division>
<Style>
<Spatium>1.74978</Spatium>
</Style>
<showInvisible>1</showInvisible>
<showUnprintable>1</showUnprintable>
<showFrames>1</showFrames>
<showMargins>0</showMargins>
<metaTag name="arranger"></metaTag>
<metaTag name="composer">Composer / arranger</metaTag>
<metaTag name="copyright"></metaTag>
<metaTag name="lyricist"></metaTag>
<metaTag name="movementNumber"></metaTag>
<metaTag name="movementTitle"></metaTag>
<metaTag name="source"></metaTag>
<metaTag name="subtitle">Subtitle</metaTag>
<metaTag name="translator"></metaTag>
<metaTag name="workNumber"></metaTag>
<metaTag name="workTitle">Untitled score</metaTag>
<Order id="orchestral">
<name>Orchestral</name>
<instrument id="piano">
<family id="keyboards">Keyboards</family>
</instrument>
<section id="woodwind" brackets="true" barLineSpan="true" thinBrackets="true">
<family>flutes</family>
<family>oboes</family>
<family>clarinets</family>
<family>saxophones</family>
<family>bassoons</family>
<unsorted group="woodwinds"/>
</section>
<section id="brass" brackets="true" barLineSpan="true" thinBrackets="true">
<family>horns</family>
<family>trumpets</family>
<family>cornets</family>
<family>flugelhorns</family>
<family>trombones</family>
<family>tubas</family>
<unsorted group="brass"/>
</section>
<section id="timpani" brackets="true" barLineSpan="true" thinBrackets="true">
<family>timpani</family>
</section>
<section id="percussion" brackets="true" barLineSpan="true" thinBrackets="true">
<family>keyboard-percussion</family>
<unsorted group="pitched-percussion"/>
<family>drums</family>
<family>unpitched-metal-percussion</family>
<family>unpitched-wooden-percussion</family>
<family>other-percussion</family>
<unsorted group="unpitched-percussion"/>
</section>
<family>keyboards</family>
<family>harps</family>
<family>organs</family>
<family>synths</family>
<unsorted/>
<soloists/>
<section id="voices" brackets="true" barLineSpan="false" thinBrackets="true">
<family>voices</family>
<family>voice-groups</family>
</section>
<section id="strings" brackets="true" barLineSpan="true" thinBrackets="true">
<family>orchestral-strings</family>
</section>
</Order>
<Part id="1">
<Staff id="1">
<StaffType group="pitched">
<name>stdNormal</name>
</StaffType>
<bracket type="1" span="2" col="0" visible="1"/>
<barLineSpan>1</barLineSpan>
</Staff>
<Staff id="2">
<StaffType group="pitched">
<name>stdNormal</name>
</StaffType>
<defaultClef>F</defaultClef>
</Staff>
<trackName>Piano</trackName>
<Instrument id="piano">
<longName>Piano</longName>
<shortName>Pno.</shortName>
<trackName>Piano</trackName>
<minPitchP>21</minPitchP>
<maxPitchP>108</maxPitchP>
<minPitchA>21</minPitchA>
<maxPitchA>108</maxPitchA>
<instrumentId>keyboard.piano</instrumentId>
<clef staff="2">F</clef>
<Channel>
<program value="0"/>
</Channel>
</Instrument>
</Part>
<Staff id="1">
<Measure>
<voice>
<KeySig>
<concertKey>0</concertKey>
</KeySig>
<TimeSig>
<sigN>3</sigN>
<sigD>2</sigD>
<stretchN>3</stretchN>
<stretchD>2</stretchD>
</TimeSig>
<Rest>
<durationType>measure</durationType>
<duration>3/2</duration>
</Rest>
</voice>
</Measure>
<Measure>
<voice>
<TimeSig>
<sigN>3</sigN>
<sigD>8</sigD>
</TimeSig>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>71</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>eighth</durationType>
<Note>
<pitch>71</pitch>
<tpc>19</tpc>
</Note>
</Chord>
</voice>
</Measure>
<Measure>
<voice>
<Rest>
<durationType>measure</durationType>
<duration>3/8</duration>
</Rest>
</voice>
</Measure>
<Measure>
<voice>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>71</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>eighth</durationType>
<Note>
<pitch>71</pitch>
<tpc>19</tpc>
</Note>
</Chord>
</voice>
</Measure>
</Staff>
<Staff id="2">
<Measure>
<voice>
<KeySig>
<concertKey>0</concertKey>
</KeySig>
<TimeSig>
<sigN>4</sigN>
<sigD>4</sigD>
</TimeSig>
<Rest>
<durationType>measure</durationType>
<duration>4/4</duration>
</Rest>
</voice>
</Measure>
<Measure>
<voice>
<TimeSig>
<sigN>3</sigN>
<sigD>8</sigD>
</TimeSig>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>59</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>eighth</durationType>
<Note>
<pitch>59</pitch>
<tpc>19</tpc>
</Note>
</Chord>
</voice>
</Measure>
<Measure>
<voice>
<Rest>
<durationType>measure</durationType>
<duration>3/8</duration>
</Rest>
</voice>
</Measure>
<Measure>
<voice>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>59</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>eighth</durationType>
<Note>
<pitch>59</pitch>
<tpc>19</tpc>
</Note>
</Chord>
</voice>
</Measure>
</Staff>
</Score>
</museScore>
Loading

0 comments on commit 43ec891

Please sign in to comment.