Skip to content
Permalink
Browse files

fix #278722: do not delete spanner segments but reuse them

  • Loading branch information...
dmitrio95 committed Nov 25, 2018
1 parent bb9b7bf commit f42943e90be9e9973d37830187d167adc8187429
1 all.h
@@ -38,6 +38,7 @@
#include <limits.h>
#include <map>
#include <set>
#include <deque>
#include <errno.h>
#include <fcntl.h>
// VStudio does not have <unistd.h>, <io.h> & <process.h> replace many functions from it...
@@ -314,8 +314,7 @@ void Score::cmdAddSpanner(Spanner* spanner, const QPointF& pos)
spanner->setTick(m->tick());
spanner->setTick2(m->endTick());
}
qDeleteAll(spanner->spannerSegments());
spanner->spannerSegments().clear();
spanner->eraseSpannerSegments();

undoAddElement(spanner);
select(spanner, SelectType::SINGLE, 0);
@@ -4332,10 +4332,7 @@ void Score::undoAddElement(Element* element)

// create tie
Tie* ntie = toTie(ne);
QList<SpannerSegment*>& segments = ntie->spannerSegments();
for (SpannerSegment* segment : segments)
delete segment;
segments.clear();
ntie->eraseSpannerSegments();
ntie->setTrack(c1->track());
ntie->setStartNote(nn1);
ntie->setEndNote(nn2);
@@ -207,7 +207,7 @@ void Glissando::scanElements(void* data, void (*func)(void*, Element*), bool all
{
func(data, this);
// don't scan segments belonging to systems; the systems themselves will scan them
for (SpannerSegment* seg : segments) {
for (SpannerSegment* seg : spannerSegments()) {
if (!seg->parent() || !seg->parent()->isSystem())
seg->scanElements(data, func, all);
}
@@ -307,7 +307,7 @@ void Glissando::layout()
// interpolate y-coord of intermediate points across total width and height
qreal xCurr = 0.0;
qreal yCurr;
for (int i = 0; i < spannerSegments().count()-1; i++) {
for (int i = 0; i < int(spannerSegments().size()-1); i++) {
SpannerSegment* segm = segmentAt(i);
xCurr += segm->ipos2().x();
yCurr = y0 + ratio * xCurr;
@@ -387,8 +387,7 @@ void Glissando::write(XmlWriter& xml) const

void Glissando::read(XmlReader& e)
{
qDeleteAll(spannerSegments());
spannerSegments().clear();
eraseSpannerSegments();

if (score()->mscVersion() < 301)
e.addSpanner(e.intAttribute("id", -1), this);
@@ -508,9 +508,7 @@ void Hairpin::write(XmlWriter& xml) const

void Hairpin::read(XmlReader& e)
{
foreach(SpannerSegment* seg, spannerSegments())
delete seg;
spannerSegments().clear();
eraseSpannerSegments();

while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
@@ -1172,6 +1172,7 @@ void Score::beamGraceNotes(Chord* mainNote, bool after)
a1->removeDeleteBeam(false);
}

#if 0 // unused
//---------------------------------------------------------
// layoutSpanner
// called after dragging a staff
@@ -1203,6 +1204,7 @@ void Score::layoutSpanner()
}
rebuildBspTree();
}
#endif

//---------------------------------------------------------
// hideEmptyStaves
@@ -3295,6 +3297,7 @@ System* Score::collectSystem(LayoutContext& lc)
Spanner* sp = interval.value;
sp->computeStartElement();
sp->computeEndElement();
lc.processedSpanners.insert(sp);
if (sp->tick() < etick && sp->tick2() >= stick) {
if (sp->isSlur())
spanner.push_back(sp);
@@ -3862,4 +3865,13 @@ void LayoutContext::layout()
score->systems().append(systemList); // TODO
}

//---------------------------------------------------------
// LayoutContext::~LayoutContext
//---------------------------------------------------------

LayoutContext::~LayoutContext()
{
for (Spanner* s : processedSpanners)
s->layoutSystemsDone();
}
}
@@ -33,6 +33,7 @@ struct LayoutContext {
Fraction sig;

QList<System*> systemList; // reusable systems
std::set<Spanner*> processedSpanners;

System* prevSystem { 0 }; // used during page layout
System* curSystem { 0 };
@@ -46,6 +47,11 @@ struct LayoutContext {
int measureNo { 0 };
int endTick;

LayoutContext() = default;
LayoutContext(const LayoutContext&) = delete;
LayoutContext& operator=(const LayoutContext&) = delete;
~LayoutContext();

void layoutLinear();
void layoutMeasureLinear(MeasureBase*);

@@ -740,19 +740,7 @@ SpannerSegment* SLine::layoutSystem(System* system)
int stick = system->firstMeasure()->tick();
int etick = system->lastMeasure()->endTick();

LineSegment* lineSegm = 0;
for (SpannerSegment* ss : segments) {
if (!ss->system()) {
lineSegm = toLineSegment(ss);
break;
}
}
if (!lineSegm) {
lineSegm = createLineSegment();
add(lineSegm);
}
lineSegm->setSystem(system);
lineSegm->setSpanner(this);
LineSegment* lineSegm = toLineSegment(getNextLayoutSystemSegment(system, [this]() { return createLineSegment(); }));

SpannerSegmentType sst;
if (tick() >= stick) {
@@ -822,35 +810,10 @@ SpannerSegment* SLine::layoutSystem(System* system)
qreal len = p2.x() - x1;
lineSegm->setPos(QPointF(p2.x() - len, p2.y()));
lineSegm->setPos2(QPointF(len, 0.0));
#if 1
QList<SpannerSegment*> sl;
for (SpannerSegment* ss : segments) {
if (ss->system())
sl.push_back(ss);
else {
qDebug("delete spanner segment %s", ss->name());
score()->selection().remove(ss);
delete ss;
}
}
segments.swap(sl);
#endif
}
break;
}
lineSegm->layout();
#if 0
QList<SpannerSegment*> sl;
for (SpannerSegment* ss : segments) {
if (ss->system())
sl.push_back(ss);
else {
qDebug("delete spanner segment %s", ss->name());
delete ss;
}
}
segments.swap(sl);
#endif
return lineSegm;
}

@@ -903,32 +866,17 @@ void SLine::layout()
int segCount = spannerSegments().size();

if (segmentsNeeded != segCount) {
fixupSegments(segmentsNeeded, [this]() { return createLineSegment(); });
if (segmentsNeeded > segCount) {
int n = segmentsNeeded - segCount;
for (int i = 0; i < n; ++i) {
LineSegment* lineSegm = createLineSegment();
add(lineSegm);
for (int i = segCount; i < segmentsNeeded; ++i) {
LineSegment* lineSegm = segmentAt(i);
// set user offset to previous segment's offset
if (segCount > 0)
lineSegm->setOffset(QPointF(0, segmentAt(segCount+i-1)->offset().y()));
lineSegm->setOffset(QPointF(0, segmentAt(i-1)->offset().y()));
else
lineSegm->setOffset(QPointF(0, offset().y()));
}
}
else {
int n = segCount - segmentsNeeded;
// qDebug("SLine: segments %d needed %d, remove %d", segCount, segmentsNeeded, n);
for (int i = 0; i < n; ++i) {
if (spannerSegments().empty()) {
qDebug("SLine::layout(): no segment %d, %d expected", i, n);
break;
}
else {
/*LineSegment* lineSegm =*/ takeLastSegment();
// delete lineSegm;
}
}
}
}

int segIdx = 0;
@@ -1018,7 +966,7 @@ void SLine::writeProperties(XmlWriter& xml) const
if (score() == gscore) {
// when used as icon
if (!spannerSegments().empty()) {
LineSegment* s = frontSegment();
const LineSegment* s = frontSegment();
xml.tag("length", s->pos2().x());
}
else
@@ -1142,9 +1090,7 @@ void SLine::write(XmlWriter& xml) const

void SLine::read(XmlReader& e)
{
foreach(SpannerSegment* seg, spannerSegments())
delete seg;
spannerSegments().clear();
eraseSpannerSegments();

if (score()->mscVersion() < 301)
e.addSpanner(e.intAttribute("id", -1), this);
@@ -109,11 +109,12 @@ class SLine : public Spanner {
qreal dashGapLen() const { return _dashGapLen; }
void setDashGapLen(qreal val) { _dashGapLen = val; }

LineSegment* frontSegment() const { return (LineSegment*)spannerSegments().front(); }
LineSegment* backSegment() const { return (LineSegment*)spannerSegments().back(); }
LineSegment* takeFirstSegment() { return (LineSegment*)spannerSegments().takeFirst(); }
LineSegment* takeLastSegment() { return (LineSegment*)spannerSegments().takeLast(); }
LineSegment* segmentAt(int n) const { return (LineSegment*)spannerSegments().at(n); }
LineSegment* frontSegment() { return toLineSegment(Spanner::frontSegment()); }
const LineSegment* frontSegment() const { return toLineSegment(Spanner::frontSegment()); }
LineSegment* backSegment() { return toLineSegment(Spanner::backSegment()); }
const LineSegment* backSegment() const { return toLineSegment(Spanner::backSegment()); }
LineSegment* segmentAt(int n) { return toLineSegment(Spanner::segmentAt(n)); }
const LineSegment* segmentAt(int n) const { return toLineSegment(Spanner::segmentAt(n)); }

virtual QVariant getProperty(Pid id) const override;
virtual bool setProperty(Pid propertyId, const QVariant&) override;
@@ -179,19 +179,7 @@ SpannerSegment* LyricsLine::layoutSystem(System* system)

// qDebug("%s %p %d-%d %d-%d", name(), this, stick, etick, tick(), tick2());

LyricsLineSegment* lineSegm = 0;
for (SpannerSegment* ss : segments) {
if (!ss->system()) {
lineSegm = toLyricsLineSegment(ss);
break;
}
}
if (!lineSegm) {
lineSegm = toLyricsLineSegment(createLineSegment());
add(lineSegm);
}
lineSegm->setSystem(system);
lineSegm->setSpanner(this);
LyricsLineSegment* lineSegm = toLyricsLineSegment(getNextLayoutSystemSegment(system, [this]() { return createLineSegment(); }));

SpannerSegmentType sst;
if (tick() >= stick) {
@@ -265,19 +253,6 @@ SpannerSegment* LyricsLine::layoutSystem(System* system)
qreal len = p2.x() - x1;
lineSegm->setPos(QPointF(p2.x() - len, p2.y()));
lineSegm->setPos2(QPointF(len, 0.0));
#if 1
QList<SpannerSegment*> sl;
for (SpannerSegment* ss : segments) {
if (ss->system())
sl.push_back(ss);
else {
qDebug("delete spanner segment %s", ss->name());
score()->selection().remove(ss);
delete ss;
}
}
segments.swap(sl);
#endif
}
break;
}
@@ -286,20 +261,8 @@ SpannerSegment* LyricsLine::layoutSystem(System* system)
// after the lyrics syllable (otherwise the melisma segment
// will be too short).
const bool tempMelismaTicks = (lyrics()->ticks() == Lyrics::TEMP_MELISMA_TICKS);
if (tempMelismaTicks && segments.size() > 0 && segments.front() == lineSegm)
if (tempMelismaTicks && spannerSegments().size() > 0 && spannerSegments().front() == lineSegm)
lineSegm->rxpos2() += lyrics()->width();
#if 0
QList<SpannerSegment*> sl;
for (SpannerSegment* ss : segments) {
if (ss->system())
sl.push_back(ss);
else {
qDebug("delete spanner segment %s", ss->name());
delete ss;
}
}
segments.swap(sl);
#endif
return lineSegm;
}

@@ -268,8 +268,7 @@ void Ottava::write(XmlWriter& xml) const

void Ottava::read(XmlReader& e)
{
qDeleteAll(spannerSegments());
spannerSegments().clear();
eraseSpannerSegments();
if (score()->mscVersion() < 301)
e.addSpanner(e.intAttribute("id", -1), this);
while (e.readNextStartElement())
@@ -3098,7 +3098,7 @@ Score::FileError MasterScore::read114(XmlReader& e)
else if (s->isTextLine()) {
yo = -5.0 * spatium();
}
if (!s->spannerSegments().isEmpty()) {
if (!s->spannerSegments().empty()) {
for (SpannerSegment* seg : s->spannerSegments()) {
if (!seg->offset().isNull())
seg->ryoffset() = seg->offset().y() - yo;
@@ -2251,7 +2251,7 @@ void readHairpin206(XmlReader& e, Hairpin* h)
h->setContinueText("");
h->setEndText("");
}
h->spannerSegments().clear();
h->eraseSpannerSegments();
#if 0
for (auto ss : h->spannerSegments()) {
ss->setOffset(QPointF());
@@ -2733,8 +2733,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
Spanner* sp = toSpanner(Element::name2Element(tag, score));
sp->setTrack(e.track());
sp->setTick(e.tick());
qDeleteAll(sp->spannerSegments());
sp->spannerSegments().clear();
sp->eraseSpannerSegments();
e.addSpanner(e.intAttribute("id", -1), sp);

if (tag == "Volta")
@@ -1097,7 +1097,7 @@ class Score : public QObject, public ScoreElement {

ChordRest* findCR(int tick, int track) const;
ChordRest* findCRinStaff(int tick, int staffIdx) const;
void layoutSpanner();
// void layoutSpanner(); // unused
void insertTime(int tickPos, int tickLen);

ScoreFont* scoreFont() const { return _scoreFont; }
@@ -468,10 +468,6 @@ static inline SpannerSegment* toSpannerSegment(ScoreElement* e) {
Q_ASSERT(e == 0 || e->isSpannerSegment());
return (SpannerSegment*)e;
}
static inline LineSegment* toLineSegment(ScoreElement* e) {
Q_ASSERT(e == 0 || e->isLineSegment());
return (LineSegment*)e;
}
static inline BSymbol* toBSymbol(ScoreElement* e) {
Q_ASSERT(e == 0 || e->isBSymbol());
return (BSymbol*)e;
@@ -535,6 +531,7 @@ static inline const a* to##a(const ScoreElement* e) { Q_ASSERT(e == 0 || e->is##
CONVERT(Beam)
CONVERT(Hook)
CONVERT(StemSlash)
CONVERT(LineSegment)
CONVERT(SlurSegment)
CONVERT(TieSegment)
CONVERT(Spacer)

0 comments on commit f42943e

Please sign in to comment.
You can’t perform that action at this time.