layout optimizations

This commit is contained in:
ws 2016-05-02 13:41:41 +02:00
parent 2aec0b81b4
commit 32c3100f80
17 changed files with 194 additions and 237 deletions

View file

@ -189,7 +189,7 @@ void BarLine::getY(qreal* y1, qreal* y2) const
staffIdx2 = score()->nstaves() - 1; staffIdx2 = score()->nstaves() - 1;
} }
Measure* measure = 0; Measure* measure = 0;
System* system; System* system = 0;
SysStaff* sysStaff0 = 0; // top staff for barline in system SysStaff* sysStaff0 = 0; // top staff for barline in system
bool systemBarLine; bool systemBarLine;
if (parent()->type() == Element::Type::SEGMENT) { if (parent()->type() == Element::Type::SEGMENT) {

View file

@ -3156,7 +3156,6 @@ Element* Chord::prevElement()
return e; return e;
} }
} }
return ChordRest::prevElement(); return ChordRest::prevElement();
} }

View file

@ -767,7 +767,7 @@ Element* ChordRest::drop(const DropData& data)
switch (e->type()) { switch (e->type()) {
case Element::Type::BREATH: case Element::Type::BREATH:
{ {
Breath* b = static_cast<Breath*>(e); Breath* b = toBreath(e);
int track = staffIdx() * VOICES; int track = staffIdx() * VOICES;
b->setTrack(track); b->setTrack(track);

View file

@ -75,6 +75,7 @@ class SlurSegment;
class Beam; class Beam;
class Hook; class Hook;
class StemSlash; class StemSlash;
class Spacer;
enum class SymId; enum class SymId;
@ -664,6 +665,7 @@ class Element : public QObject, public ScoreElement {
CONVERT(Hook, HOOK); CONVERT(Hook, HOOK);
CONVERT(StemSlash, STEM_SLASH); CONVERT(StemSlash, STEM_SLASH);
CONVERT(SlurSegment, SLUR_SEGMENT); CONVERT(SlurSegment, SLUR_SEGMENT);
CONVERT(Spacer, SPACER);
#undef CONVERT #undef CONVERT
}; };
@ -726,6 +728,7 @@ static inline const a* to##a(const Element* e) { Q_ASSERT(e == 0 || e->type() ==
CONVERT(Hook, HOOK); CONVERT(Hook, HOOK);
CONVERT(StemSlash, STEM_SLASH); CONVERT(StemSlash, STEM_SLASH);
CONVERT(SlurSegment, SLUR_SEGMENT); CONVERT(SlurSegment, SLUR_SEGMENT);
CONVERT(Spacer, SPACER);
#undef CONVERT #undef CONVERT
//--------------------------------------------------------- //---------------------------------------------------------

View file

@ -1369,7 +1369,7 @@ void Score::addSystemHeader(Measure* m, bool isFirstSystem)
BarLine* bl = 0; BarLine* bl = 0;
Segment* s = m->findSegment(Segment::Type::BeginBarLine, tick); Segment* s = m->findSegment(Segment::Type::BeginBarLine, tick);
if (s && s->isBeginBarLineType()) if (s)
bl = toBarLine(s->element(0)); bl = toBarLine(s->element(0));
if ((nVisible > 1 && score()->styleB(StyleIdx::startBarlineMultiple)) || (nVisible <= 1 && score()->styleB(StyleIdx::startBarlineSingle))) { if ((nVisible > 1 && score()->styleB(StyleIdx::startBarlineMultiple)) || (nVisible <= 1 && score()->styleB(StyleIdx::startBarlineSingle))) {
@ -1836,51 +1836,26 @@ static void layoutPage(Page* page, qreal restHeight)
} }
//--------------------------------------------------------- //---------------------------------------------------------
// sff // Spring
// compute 1/Force for a given Extend
//--------------------------------------------------------- //---------------------------------------------------------
qreal sff(qreal x, qreal xMin, const SpringMap& springs) struct Spring {
{
if (x <= xMin)
return 0.0;
auto i = springs.begin();
qreal c = i->second.stretch;
if (c == 0.0) //DEBUG
c = 1.1;
qreal f = 0.0;
for (; i != springs.end();) {
xMin -= i->second.fix;
f = (x - xMin) / c;
++i;
if (i == springs.end() || f <= i->first)
break;
c += i->second.stretch;
}
return f;
}
//---------------------------------------------------------
// Spring2
//---------------------------------------------------------
struct Spring2 {
int seg; int seg;
qreal stretch; qreal stretch;
qreal fix; qreal fix;
Spring2(int i, qreal s, qreal f) : seg(i), stretch(s), fix(f) {} Spring(int i, qreal s, qreal f) : seg(i), stretch(s), fix(f) {}
}; };
typedef std::multimap<qreal, Spring2, std::less<qreal> > SpringMap2; typedef std::multimap<qreal, Spring, std::less<qreal> > SpringMap;
//--------------------------------------------------------- //---------------------------------------------------------
// sff2 // sff2
// compute 1/Force for a given Extend // compute 1/Force for a given Extend
//--------------------------------------------------------- //---------------------------------------------------------
qreal sff2(qreal x, qreal xMin, const SpringMap2& springs) static qreal sff2(qreal width, qreal xMin, const SpringMap& springs)
{ {
if (x <= xMin) if (width <= xMin)
return 0.0; return 0.0;
auto i = springs.begin(); auto i = springs.begin();
qreal c = i->second.stretch; qreal c = i->second.stretch;
@ -1889,7 +1864,7 @@ qreal sff2(qreal x, qreal xMin, const SpringMap2& springs)
qreal f = 0.0; qreal f = 0.0;
for (; i != springs.end();) { for (; i != springs.end();) {
xMin -= i->second.fix; xMin -= i->second.fix;
f = (x - xMin) / c; f = (width - xMin) / c;
++i; ++i;
if (i == springs.end() || f <= i->first) if (i == springs.end() || f <= i->first)
break; break;
@ -1898,7 +1873,6 @@ qreal sff2(qreal x, qreal xMin, const SpringMap2& springs)
return f; return f;
} }
//--------------------------------------------------------- //---------------------------------------------------------
// respace // respace
//--------------------------------------------------------- //---------------------------------------------------------
@ -1927,7 +1901,7 @@ void Score::respace(std::vector<ChordRest*>* elements)
// compute stretches // compute stretches
//--------------------------------------------------- //---------------------------------------------------
SpringMap2 springs; SpringMap springs;
qreal minimum = 0.0; qreal minimum = 0.0;
for (int i = 0; i < n-1; ++i) { for (int i = 0; i < n-1; ++i) {
qreal w = width[i]; qreal w = width[i];
@ -1935,7 +1909,7 @@ void Score::respace(std::vector<ChordRest*>* elements)
qreal str = 1.0 + 0.865617 * log(qreal(t) / qreal(minTick)); qreal str = 1.0 + 0.865617 * log(qreal(t) / qreal(minTick));
qreal d = w / str; qreal d = w / str;
springs.insert(std::pair<qreal, Spring2>(d, Spring2(i, str, w))); springs.insert(std::pair<qreal, Spring>(d, Spring(i, str, w)));
minimum += w; minimum += w;
} }
@ -2680,11 +2654,8 @@ void Score::getNextMeasure(LayoutContext& lc)
} }
else if (isMaster() && s->isChordRestType()) { else if (isMaster() && s->isChordRestType()) {
for (Element* e : s->annotations()) { for (Element* e : s->annotations()) {
if (e->isTempoText()) { if (!e->isTempoText()) // layout tempotext after stretchMeasure
TempoText* tt = toTempoText(e); e->layout();
setTempo(tt->segment(), tt->tempo());
}
e->layout();
} }
qreal stretch = 0.0; qreal stretch = 0.0;
for (Element* e : s->elist()) { for (Element* e : s->elist()) {
@ -3250,6 +3221,14 @@ System* Score::collectSystem(LayoutContext& lc)
cr->beam()->layout(); cr->beam()->layout();
} }
} }
for (Element* e : s->annotations()) {
if (e->isTempoText()) {
TempoText* tt = toTempoText(e);
setTempo(tt->segment(), tt->tempo());
tt->layout();
s->staffShape(tt->staffIdx()).add(tt->shape());
}
}
} }
} }
system->layout2(); system->layout2();

View file

@ -2,7 +2,7 @@
// MuseScore // MuseScore
// Music Composition & Notation // Music Composition & Notation
// //
// Copyright (C) 2002-2011 Werner Schweer // Copyright (C) 2002-2016 Werner Schweer
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 // it under the terms of the GNU General Public License version 2
@ -17,17 +17,6 @@ namespace Ms {
class Segment; class Segment;
//---------------------------------------------------------
// Spring
//---------------------------------------------------------
struct Spring {
Segment* seg;
qreal stretch;
qreal fix;
Spring(Segment* s, qreal str) : seg(s), stretch(str), fix(s->width()) {}
};
//--------------------------------------------------------- //---------------------------------------------------------
// LayoutContext // LayoutContext
// temp values used during layout // temp values used during layout
@ -58,10 +47,6 @@ struct LayoutContext {
int adjustMeasureNo(MeasureBase*); int adjustMeasureNo(MeasureBase*);
}; };
typedef std::multimap<qreal, Spring, std::less<qreal> > SpringMap;
extern qreal sff(qreal x, qreal xMin, const SpringMap& springs);
} // namespace Ms } // namespace Ms
#endif #endif

View file

@ -620,8 +620,8 @@ void Measure::add(Element* e)
break; break;
case Element::Type::SEGMENT: case Element::Type::SEGMENT:
{ {
Segment* seg = static_cast<Segment*>(e); Segment* seg = toSegment(e);
int t = seg->tick(); int t = seg->tick();
Segment::Type st = seg->segmentType(); Segment::Type st = seg->segmentType();
Segment* s; Segment* s;
for (s = first(); s && s->tick() < t; s = s->next()) for (s = first(); s && s->tick() < t; s = s->next())
@ -675,7 +675,6 @@ void Measure::add(Element* e)
MeasureBase::add(e); MeasureBase::add(e);
break; break;
} }
} }
//--------------------------------------------------------- //---------------------------------------------------------
@ -694,9 +693,9 @@ void Measure::remove(Element* e)
break; break;
case Element::Type::SPACER: case Element::Type::SPACER:
if (static_cast<Spacer*>(e)->spacerType() == SpacerType::DOWN) if (toSpacer(e)->spacerType() == SpacerType::DOWN)
_mstaves[e->staffIdx()]->_vspacerDown = 0; _mstaves[e->staffIdx()]->_vspacerDown = 0;
else if (static_cast<Spacer*>(e)->spacerType() == SpacerType::UP) else if (toSpacer(e)->spacerType() == SpacerType::UP)
_mstaves[e->staffIdx()]->_vspacerUp = 0; _mstaves[e->staffIdx()]->_vspacerUp = 0;
break; break;
@ -3199,6 +3198,10 @@ qreal Measure::userStretch() const
return (score()->layoutMode() == LayoutMode::FLOAT ? 1.0 : _userStretch); return (score()->layoutMode() == LayoutMode::FLOAT ? 1.0 : _userStretch);
} }
//---------------------------------------------------------
// nextElementStaff
//---------------------------------------------------------
Element* Measure::nextElementStaff(int staff) Element* Measure::nextElementStaff(int staff)
{ {
Segment* firstSeg = segments().first(); Segment* firstSeg = segments().first();
@ -3207,6 +3210,10 @@ Element* Measure::nextElementStaff(int staff)
return score()->firstElement(); return score()->firstElement();
} }
//---------------------------------------------------------
// prevElementStaff
//---------------------------------------------------------
Element* Measure::prevElementStaff(int staff) Element* Measure::prevElementStaff(int staff)
{ {
Measure* prevM = prevMeasureMM(); Measure* prevM = prevMeasureMM();
@ -3229,108 +3236,116 @@ QString Measure::accessibleInfo() const
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// stretchMeasure // stretchMeasure
// resize width of measure to stretch // resize width of measure to targetWidth
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Measure::stretchMeasure(qreal stretch) void Measure::stretchMeasure(qreal targetWidth)
{ {
bbox().setWidth(stretch); bbox().setWidth(targetWidth);
int nstaves = score()->nstaves(); //---------------------------------------------------
int minTick = 100000; // compute minTick and set ticks for all segments
//---------------------------------------------------
for (auto& s : _segments) { int minTick = ticks();
int nticks; Segment* ns = first();
if (s.isChordRestType()) { while (ns) {
const Segment* nseg = s.next(Segment::Type::ChordRest); Segment* s = ns;
nticks = (nseg ? nseg->rtick() : ticks()) - s.rtick(); ns = s->next();
if (nticks) { int nticks = (ns ? ns->rtick() : ticks()) - s->rtick();
if (nticks < minTick) if (nticks) {
minTick = nticks; if (nticks < minTick)
} minTick = nticks;
} }
else s->setTicks(nticks);
nticks = 0;
s.setTicks(nticks);
} }
//--------------------------------------------------- //---------------------------------------------------
// computeStretch // compute stretch
//--------------------------------------------------- //---------------------------------------------------
SpringMap springs; // typedef std::multimap<qreal, Segment*, std::less<qreal>> SpringMap;
qreal minimum = first()->pos().x(); std::multimap<qreal, Segment*> springs;
for (auto& s : _segments) { Q_ASSERT(minTick > 0);
qreal str = 1.0;
qreal d;
qreal minimumWidth = first()->pos().x();
for (Segment& s : _segments) {
int t = s.ticks(); int t = s.ticks();
if (t) { if (t) {
if (minTick > 0) qreal str = 1.0 + 0.865617 * log(qreal(t) / qreal(minTick)); // .6 * log(t / minTick) / log(2);
// str += .6 * log(qreal(t) / qreal(minTick)) / log(2.0); qreal d = s.width() / str;
str = 1.0 + 0.865617 * log(qreal(t) / qreal(minTick)); s.setStretch(str);
d = s.width() / str; springs.insert(std::pair<qreal, Segment*>(d, &s));
} }
else { minimumWidth += s.width();
str = 0.0; // dont stretch timeSig and key
d = 100000000.0; // CHECK
}
springs.insert(std::pair<qreal, Spring>(d, Spring(&s, str)));
minimum += s.width();
} }
//--------------------------------------------------- //---------------------------------------------------
// distribute stretch to segments // compute 1/Force for a given Extend
//--------------------------------------------------- //---------------------------------------------------
qreal force = sff(stretch, minimum, springs); if (targetWidth > minimumWidth) {
qreal force = 0;
qreal c = 0.0;
for (auto i = springs.begin();;) {
c += i->second->stretch();
minimumWidth -= i->second->width();
qreal f = (targetWidth - minimumWidth) / c;
++i;
if (i == springs.end() || f <= i->first) {
force = f;
break;
}
}
//---------------------------------------------------
// distribute stretch to segments
//---------------------------------------------------
for (auto& i : springs) { for (auto& i : springs) {
qreal stretch = force * i.second.stretch; qreal width = force * i.second->stretch();
if (stretch < i.second.fix) if (width > i.second->width())
stretch = i.second.fix; i.second->setWidth(width);
i.second.seg->setWidth(stretch); }
}
qreal x = first()->pos().x(); //---------------------------------------------------
for (Segment* s = first(); s; s = s->next()) { // move segments to final position
s->rxpos() = x; //---------------------------------------------------
x += s->width();
qreal x = first()->pos().x();
for (Segment& s : _segments) {
s.rxpos() = x;
x += s.width();
}
} }
//--------------------------------------------------- //---------------------------------------------------
// layout individual elements // layout individual elements
//--------------------------------------------------- //---------------------------------------------------
int tracks = nstaves * VOICES; for (Segment& s : _segments) {
for (Segment* s = first(); s; s = s->next()) { for (Element* e : s.elist()) {
for (int track = 0; track < tracks; ++track) { if (!e)
if (!score()->staff(track/VOICES)->show()) {
track += VOICES-1;
continue;
}
Element* e = s->element(track);
if (e == 0)
continue; continue;
Element::Type t = e->type(); Element::Type t = e->type();
Rest* rest = static_cast<Rest*>(e); int staffIdx = e->staffIdx();
if (t == Element::Type::REPEAT_MEASURE || (t == Element::Type::REST && (isMMRest() || rest->isFullMeasureRest()))) { if (t == Element::Type::REPEAT_MEASURE || (t == Element::Type::REST && (isMMRest() || toRest(e)->isFullMeasureRest()))) {
// //
// element has to be centered in free space // element has to be centered in free space
// x1 - left measure position of free space // x1 - left measure position of free space
// x2 - right measure position of free space // x2 - right measure position of free space
Segment* s1 = s->prev() ? s->prev() : 0; Segment* s1 = s.prev() ? s.prev() : 0;
Segment* s2; Segment* s2;
for (s2 = s->next(); s2; s2 = s2->next()) { for (s2 = s.next(); s2; s2 = s2->next()) {
if (!s2->isChordRestType()) if (!s2->isChordRestType())
break; break;
} }
qreal x1 = s1 ? s1->x() + s1->minRight() : 0; qreal x1 = s1 ? s1->x() + s1->minRight() : 0;
qreal x2 = s2 ? s2->x() - s2->minLeft() : width(); qreal x2 = s2 ? s2->x() - s2->minLeft() : targetWidth;
if (isMMRest()) { if (isMMRest()) {
Rest* rest = toRest(e);
// //
// center multi measure rest // center multi measure rest
// //
@ -3338,19 +3353,19 @@ void Measure::stretchMeasure(qreal stretch)
qreal w = x2 - x1 - 2 * d; qreal w = x2 - x1 - 2 * d;
rest->setMMWidth(w); rest->setMMWidth(w);
StaffLines* sl = _mstaves[track/VOICES]->lines; StaffLines* sl = _mstaves[staffIdx]->lines;
qreal x = x1 - s->x() + d; qreal x = x1 - s.x() + d;
e->setPos(x, sl->staffHeight() * .5); // center vertically in measure e->setPos(x, sl->staffHeight() * .5); // center vertically in measure
rest->layout(); rest->layout();
s->createShape(track/VOICES); s.createShape(staffIdx);
} }
else { // if (rest->isFullMeasureRest()) { else { // if (rest->isFullMeasureRest()) {
// //
// center full measure rest // center full measure rest
// //
rest->rxpos() = (x2 - x1 - e->width()) * .5 + x1 - s->x() - e->bbox().x(); e->rxpos() = (x2 - x1 - e->width()) * .5 + x1 - s.x() - e->bbox().x();
rest->adjustReadPos(); e->adjustReadPos();
s->createShape(track/VOICES); // DEBUG s.createShape(staffIdx); // DEBUG
} }
} }
else if (t == Element::Type::REST) else if (t == Element::Type::REST)

View file

@ -263,8 +263,8 @@ class CmdState {
public: public:
LayoutFlags layoutFlags; LayoutFlags layoutFlags;
bool _excerptsChanged; bool _excerptsChanged { false };
bool _instrumentsChanged; bool _instrumentsChanged { false };
void reset(); void reset();
UpdateMode updateMode() const { return _updateMode; } UpdateMode updateMode() const { return _updateMode; }

View file

@ -767,10 +767,12 @@ void Segment::checkEmpty() const
// tick // tick
//--------------------------------------------------------- //---------------------------------------------------------
#if 0
int Segment::tick() const int Segment::tick() const
{ {
return _tick + measure()->tick(); return _tick + measure()->tick();
} }
#endif
//--------------------------------------------------------- //---------------------------------------------------------
// setTick // setTick
@ -1332,7 +1334,7 @@ void Segment::createShape(int staffIdx)
s.add(e->shape()); s.add(e->shape());
} }
for (Element* e : _annotations) { for (Element* e : _annotations) {
if (e->staffIdx() == staffIdx && e->visible()) if (e->staffIdx() == staffIdx && e->visible() && !e->isTempoText())
s.add(e->shape()); s.add(e->shape());
} }
} }
@ -1359,18 +1361,22 @@ qreal Segment::minRight() const
qreal Segment::minLeft(const Shape& sl) const qreal Segment::minLeft(const Shape& sl) const
{ {
qreal distance = 0.0; qreal distance = 0.0;
for (const Shape& sh : shapes()) for (const Shape& sh : shapes()) {
distance = qMax(distance, sl.minHorizontalDistance(sh)); qreal d = sl.minHorizontalDistance(sh);
if (d > distance)
distance = d;
}
return distance; return distance;
} }
qreal Segment::minLeft() const qreal Segment::minLeft() const
{ {
qreal distance = 0.0; qreal distance = 0.0;
for (const Shape& sh : shapes()) for (const Shape& sh : shapes()) {
distance = qMax(distance, sh.left()); qreal l = sh.left();
if (l > distance)
distance = l;
}
return distance; return distance;
} }
@ -1410,8 +1416,8 @@ qreal Segment::minHorizontalDistance(Segment* ns, bool systemHeaderGap) const
} }
else else
d = score()->styleP(StyleIdx::barNoteDistance); d = score()->styleP(StyleIdx::barNoteDistance);
qreal dd = minRight() + ns->minLeft(); qreal dd = minRight() + ns->minLeft() + spatium();
w = qMax(d, dd + spatium()); w = qMax(d, dd);
// d -= ns->minLeft() * .7; // hack // d -= ns->minLeft() * .7; // hack
// d = qMax(d, ns->minLeft()); // d = qMax(d, ns->minLeft());
// d = qMax(d, spatium()); // minimum distance is one spatium // d = qMax(d, spatium()); // minimum distance is one spatium

View file

@ -66,40 +66,42 @@ class Segment : public Element {
Q_PROPERTY(int tick READ tick) Q_PROPERTY(int tick READ tick)
Q_ENUMS(Type) Q_ENUMS(Type)
public: public:
enum class Type { // Type need to be in the order in which they appear in a measure
Invalid = 0x0, enum class Type {
BeginBarLine = 0x1, Invalid = 0x0,
Clef = 0x2, // type from Clef to TimeSig BeginBarLine = 0x1,
KeySig = 0x4, // need to be in the order in which they Clef = 0x2,
Ambitus = 0x8, // appear in a measure KeySig = 0x4,
TimeSig = 0x10, Ambitus = 0x8,
StartRepeatBarLine = 0x20, TimeSig = 0x10,
BarLine = 0x40, StartRepeatBarLine = 0x20,
Breath = 0x80, BarLine = 0x40,
ChordRest = 0x100, Breath = 0x80,
EndBarLine = 0x200, ChordRest = 0x100,
KeySigAnnounce = 0x400, EndBarLine = 0x200,
TimeSigAnnounce = 0x800, KeySigAnnounce = 0x400,
All = -1 TimeSigAnnounce = 0x800,
}; All = -1
};
private: private:
Segment* _next; // linked list of segments inside a measure Segment* _next; // linked list of segments inside a measure
Segment* _prev; Segment* _prev;
mutable bool _empty; // cached value std::vector<Element*> _annotations;
mutable bool _written { false }; // used for write() std::vector<Element*> _elist; // Element storage, size = staves * VOICES.
std::vector<Shape> _shapes; // size = staves
std::vector<qreal> _dotPosX; // size = staves
Type _segmentType { Type::Invalid }; Spatium _extraLeadingSpace;
qreal _stretch;
int _tick; int _tick;
int _ticks; int _ticks;
Spatium _extraLeadingSpace; Type _segmentType { Type::Invalid };
std::vector<Element*> _annotations; mutable bool _empty; // cached value
std::vector<Element*> _elist; ///< Element storage, size = staves * VOICES. mutable bool _written { false }; // used for write()
std::vector<Shape> _shapes; // size = staves
std::vector<qreal> _dotPosX; ///< size = staves
void init(); void init();
void checkEmpty() const; void checkEmpty() const;
@ -176,8 +178,11 @@ public:
void removeGeneratedElements(); void removeGeneratedElements();
bool empty() const { return _empty; } bool empty() const { return _empty; }
void fixStaffIdx(); void fixStaffIdx();
qreal stretch() const { return _stretch; }
void setStretch(qreal v) { _stretch = v; }
void setTick(int); void setTick(int);
virtual int tick() const override; virtual int tick() const override { return _tick + parent()->tick(); }
virtual int rtick() const override { return _tick; } // tickposition relative to measure start virtual int rtick() const override { return _tick; } // tickposition relative to measure start
void setRtick(int val) { _tick = val; } void setRtick(int val) { _tick = val; }
int ticks() const { return _ticks; } int ticks() const { return _ticks; }

View file

@ -83,6 +83,10 @@ void SegmentList::check()
if (l != _last) { if (l != _last) {
qFatal("SegmentList::check: bad last"); qFatal("SegmentList::check: bad last");
} }
if (f->prev())
qFatal("SegmentList::check: first has prev");
if (l->next())
qFatal("SegmentList::check: last has next");
if (n != _size) { if (n != _size) {
qFatal("SegmentList::check: counted %d but _size is %d", n, _size); qFatal("SegmentList::check: counted %d but _size is %d", n, _size);
_size = n; _size = n;
@ -107,34 +111,46 @@ void SegmentList::insert(Segment* e, Segment* el)
e->setPrev(el->prev()); e->setPrev(el->prev());
el->prev()->setNext(e); el->prev()->setNext(e);
el->setPrev(e); el->setPrev(e);
check();
} }
check();
} }
//--------------------------------------------------------- //---------------------------------------------------------
// remove // remove
//--------------------------------------------------------- //---------------------------------------------------------
void SegmentList::remove(Segment* el) void SegmentList::remove(Segment* e)
{ {
#ifndef NDEBUG
check();
bool found = false;
for (Segment* s = _first; s; s = s->next()) {
if (e == s) {
found = true;
break;
}
}
if (!found) {
qFatal("segment %p %s not in list", e, e->subTypeName());
}
#endif
--_size; --_size;
if (el == _first) { if (e == _first) {
_first = _first->next(); _first = _first->next();
if (_first) if (_first)
_first->setPrev(0); _first->setPrev(0);
if (el == _last) if (e == _last)
_last = 0; _last = 0;
} }
else if (el == _last) { else if (e == _last) {
_last = _last->prev(); _last = _last->prev();
if (_last) if (_last)
_last->setNext(0); _last->setNext(0);
} }
else { else {
el->prev()->setNext(el->next()); e->prev()->setNext(e->next());
el->next()->setPrev(el->prev()); e->next()->setPrev(e->prev());
} }
check();
} }
//--------------------------------------------------------- //---------------------------------------------------------
@ -171,54 +187,6 @@ void SegmentList::push_front(Segment* e)
check(); check();
} }
//---------------------------------------------------------
// insert
//---------------------------------------------------------
void SegmentList::insert(Segment* seg)
{
#ifndef NDEBUG
// qDebug("insertSeg <%s> %p %p %p", seg->subTypeName(), seg->prev(), seg, seg->next());
check();
for (Segment* s = _first; s; s = s->next()) {
if (s == seg) {
qFatal("SegmentList::insert: already in list");
}
}
if (seg->prev()) {
Segment* s;
for (s = _first; s; s = s->next()) {
if (s == seg->prev())
break;
}
if (s != seg->prev()) {
qFatal("SegmentList::insert: seg->prev() not in list");
}
}
if (seg->next()) {
Segment* s;
for (s = _first; s; s = s->next()) {
if (s == seg->next())
break;
}
if (s != seg->next()) {
qFatal("SegmentList::insert: seg->next() not in list");
}
}
#endif
if (seg->prev())
seg->prev()->setNext(seg);
else
_first = seg;
if (seg->next())
seg->next()->setPrev(seg);
else
_last = seg;
++_size;
check();
}
//--------------------------------------------------------- //---------------------------------------------------------
// firstCRSegment // firstCRSegment
//--------------------------------------------------------- //---------------------------------------------------------

View file

@ -45,8 +45,7 @@ class SegmentList {
void remove(Segment*); void remove(Segment*);
void push_back(Segment*); void push_back(Segment*);
void push_front(Segment*); void push_front(Segment*);
void insert(Segment*); void insert(Segment* e, Segment* el); // insert e before el
void insert(Segment* e, Segment* el);
class iterator { class iterator {
Segment* p; Segment* p;

View file

@ -15,7 +15,7 @@
namespace Ms { namespace Ms {
// #define DEBUG_SHAPES #define DEBUG_SHAPES
class Segment; class Segment;

View file

@ -279,31 +279,29 @@ QVariant TempoText::propertyDefault(P_ID id) const
//--------------------------------------------------------- //---------------------------------------------------------
// layout // layout
// called after Measure->stretchMeasure()
//--------------------------------------------------------- //---------------------------------------------------------
void TempoText::layout() void TempoText::layout()
{ {
setPos(textStyle().offset(spatium())); setPos(textStyle().offset(spatium()));
Text::layout1(); Text::layout1();
// tempo text on first chordrest of measure should align over time sig if present
//
Segment* s = segment(); Segment* s = segment();
if (s && !s->rtick()) { if (s && !s->rtick()) {
// tempo text on first chordrest of measure should align over time sig if present
Segment* p = segment()->prev(Segment::Type::TimeSig); Segment* p = segment()->prev(Segment::Type::TimeSig);
if (p) { if (p) {
rxpos() -= s->x() - p->x(); rxpos() -= s->x() - p->x();
Element* e = p->element(staffIdx() * VOICES); Element* e = p->element(staffIdx() * VOICES);
if (e) if (e)
rxpos() += e->x(); rxpos() += e->x();
// correct user offset in older scores
if (score()->mscVersion() <= 114 && !userOff().isNull())
rUserXoffset() += s->x() - p->x();
} }
} }
if (placement() == Element::Placement::BELOW) {
if (placement() == Element::Placement::BELOW)
rypos() = -rypos() + 4 * spatium(); rypos() = -rypos() + 4 * spatium();
// rUserYoffset() *= -1;
// text height ?
}
adjustReadPos(); adjustReadPos();
} }

View file

@ -194,7 +194,7 @@
<Segment> <Segment>
<subtype>0</subtype> <subtype>0</subtype>
<off2 x="0" y="0"/> <off2 x="0" y="0"/>
<pos x="33.8175" y="6.60645"/> <pos x="34.0159" y="6.60645"/>
</Segment> </Segment>
<beginText> <beginText>
<text>cresc.</text> <text>cresc.</text>

View file

@ -194,7 +194,7 @@
<Segment> <Segment>
<subtype>0</subtype> <subtype>0</subtype>
<off2 x="0" y="0"/> <off2 x="0" y="0"/>
<pos x="33.8175" y="6.60645"/> <pos x="34.0159" y="6.60645"/>
</Segment> </Segment>
<beginText> <beginText>
<text>cresc.</text> <text>cresc.</text>

View file

@ -337,7 +337,7 @@ MasterScore* TestParts::doAddBreath()
Measure* m = score->firstMeasure(); Measure* m = score->firstMeasure();
Segment* s = m->tick2segment(MScore::division); Segment* s = m->tick2segment(MScore::division);
Ms::Chord* chord = static_cast<Ms::Chord*>(s->element(0)); Ms::Chord* chord = toChord(s->element(0));
Note* note = chord->upNote(); Note* note = chord->upNote();
DropData dd; DropData dd;
dd.view = 0; dd.view = 0;