MuseScore/libmscore/splitMeasure.cpp
lasconic c08b67ff90 fix #183846 split irreg-len meas shouldn't add rest
This fixes an bug which produced corrupted measures when splitting irregular length measures.  In Score::cmdSplitMeasure() after the newly split measures are first created, if their new actual length was greater than their nominal length, then Measure::adjustToLen() would append additional padding rests at the end of the measure.  However, the subsequent range.write() assumed that the measures were entirely empty before copying contents from the original measure into the new measures.  The extra padding rests were unnecessary, and caused the resulting measures to contain too many notes than their actual length, hence the corruption.

The fix here is to add a default boolean parameter to adjustToLen() called appendRestsIfNecessary which is true by default so as to not change behavior when it is called without specifiying the parameter. However, cmdSplitMeasure() will call adjustToLen with that boolean explicitly false, so that the new measures don't get unnecessary rests.
2017-03-24 17:31:25 +01:00

87 lines
2.6 KiB
C++

//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2002-2012 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation and appearing in
// the file LICENCE.GPL
//=============================================================================
#include "score.h"
#include "measure.h"
#include "segment.h"
#include "chordrest.h"
#include "range.h"
#include "tuplet.h"
#include "spanner.h"
namespace Ms {
//---------------------------------------------------------
// cmdSplitMeasure
//---------------------------------------------------------
void Score::cmdSplitMeasure(ChordRest* cr)
{
startCmd();
splitMeasure(cr->segment());
endCmd();
}
//---------------------------------------------------------
// splitMeasure
// return true on success
//---------------------------------------------------------
void Score::splitMeasure(Segment* segment)
{
if (segment->rtick() == 0) {
MScore::setError(CANNOT_SPLIT_MEASURE_FIRST_BEAT);
return;
}
if (segment->splitsTuplet()) {
MScore::setError(CANNOT_SPLIT_MEASURE_TUPLET);
return;
}
Measure* measure = segment->measure();
ScoreRange range;
range.read(measure->first(), measure->last());
int stick = measure->tick();
int etick = measure->endTick();
for (auto i : spanner()) {
Spanner* s = i.second;
if (s->tick() >= stick && s->tick() < etick)
s->setStartElement(0);
if (s->tick2() >= stick && s->tick2() < etick)
s->setEndElement(0);
}
MeasureBase* nm = measure->next();
undoRemoveMeasures(measure, measure);
undoInsertTime(measure->tick(), -measure->ticks());
// create empty measures:
insertMeasure(ElementType::MEASURE, nm, true);
Measure* m2 = toMeasure(nm ? nm->prev() : lastMeasure());
insertMeasure(ElementType::MEASURE, m2, true);
Measure* m1 = toMeasure(m2->prev());
int tick = segment->tick();
m1->setTick(measure->tick());
m2->setTick(tick);
int ticks1 = segment->tick() - measure->tick();
int ticks2 = measure->ticks() - ticks1;
m1->setTimesig(measure->timesig());
m2->setTimesig(measure->timesig());
m1->adjustToLen(Fraction::fromTicks(ticks1), false);
m2->adjustToLen(Fraction::fromTicks(ticks2), false);
range.write(this, m1->tick());
}
}