diff --git a/libmscore/layout.cpp b/libmscore/layout.cpp index a32a2c2fdd..0a680bdc1e 100644 --- a/libmscore/layout.cpp +++ b/libmscore/layout.cpp @@ -3507,6 +3507,9 @@ void Score::layoutSystemElements(System* system, LayoutContext& lc) if (!mb->isMeasure()) continue; Measure* m = toMeasure(mb); + if (MeasureNumber* mno = m->noText(staffIdx)) + ss->skyline().add(mno->bbox().translated(m->pos() + mno->pos())); + ss->skyline().add(m->staffLines(staffIdx)->bbox().translated(m->pos())); for (Segment& s : m->segments()) { if (!s.enabled() || s.isTimeSigType()) // hack: ignore time signatures continue; @@ -3534,7 +3537,6 @@ void Score::layoutSystemElements(System* system, LayoutContext& lc) } for (auto n : c->notes()) notes.push_back(n); - std::list fingerings; for (Note* note : notes) { for (Element* e : note->el()) { if (e->isFingering()) { @@ -3561,10 +3563,6 @@ void Score::layoutSystemElements(System* system, LayoutContext& lc) } } } - ss->skyline().add(m->staffLines(staffIdx)->bbox().translated(m->pos())); - MeasureNumber* mno = m->noText(staffIdx); - if (mno) - ss->skyline().add(mno->bbox().translated(m->pos() + mno->pos())); } } diff --git a/libmscore/skyline.cpp b/libmscore/skyline.cpp index e8fe489968..bde8ec96d0 100644 --- a/libmscore/skyline.cpp +++ b/libmscore/skyline.cpp @@ -37,6 +37,46 @@ void Skyline::add(const QRectF& r) _south.add(r.x(), r.bottom(), r.width()); } +//--------------------------------------------------------- +// insert +//--------------------------------------------------------- + +SkylineLine::SegIter SkylineLine::insert(SegIter i, qreal x, qreal y, qreal w) + { + const qreal xr = x + w; + // Only x coordinate change is handled here as width change gets handled + // in SkylineLine::add(). + if (i != seg.end() && xr > i->x) + i->x = xr; + return seg.emplace(i, x, y, w); + } + +//--------------------------------------------------------- +// append +//--------------------------------------------------------- + +void SkylineLine::append(qreal x, qreal y, qreal w) + { + seg.emplace_back(x, y, w); + } + +//--------------------------------------------------------- +// getApproxPosition +//--------------------------------------------------------- + +SkylineLine::SegIter SkylineLine::find(qreal x) + { + auto it = std::upper_bound(seg.begin(), seg.end(), x, [](qreal x, const SkylineSegment& s) { return x < s.x; }); + if (it == seg.begin()) + return it; + return (--it); + } + +SkylineLine::SegConstIter SkylineLine::find(qreal x) const + { + return const_cast(this)->find(x); + } + //--------------------------------------------------------- // add //--------------------------------------------------------- @@ -72,8 +112,10 @@ void SkylineLine::add(qreal x, qreal y, qreal w) } DP("===add %f %f %f\n", x, y, w); - qreal cx = 0.0; - for (auto i = begin(); i != end(); ++i) { + + SegIter i = find(x); + qreal cx = seg.empty() ? 0.0 : i->x; + for (; i != seg.end(); ++i) { qreal cy = i->y; if ((x + w) <= cx) // A return; // break; @@ -93,7 +135,7 @@ void SkylineLine::add(qreal x, qreal y, qreal w) if (w1 > 0.0000001) { i->w = w1; ++i; - i = insert(i, SkylineSegment(y, w2)); + i = insert(i, x, y, w2); DP(" A w1 %f w2 %f\n", w1, w2); } else { @@ -104,7 +146,7 @@ void SkylineLine::add(qreal x, qreal y, qreal w) if (w3 > 0.0000001) { ++i; DP(" C w3 %f\n", w3); - insert(i, SkylineSegment(cy, w3)); + insert(i, x + w2, cy, w3); } return; } @@ -116,7 +158,7 @@ void SkylineLine::add(qreal x, qreal y, qreal w) qreal w1 = x + w - cx; i->w -= w1; DP(" add(C) cx %f y %f w %f w1 %f\n", cx, y, w1, i->w); - insert(i, SkylineSegment(y, w1)); + insert(i, cx, y, w1); return; } else { // D @@ -127,7 +169,7 @@ void SkylineLine::add(qreal x, qreal y, qreal w) cx += w1; DP(" add(D) %f %f\n", y, w2); ++i; - i = insert(i, SkylineSegment(y, w2)); + i = insert(i, cx, y, w2); } } cx += i->w; @@ -136,13 +178,13 @@ void SkylineLine::add(qreal x, qreal y, qreal w) if (x > cx) { qreal cy = north ? MAXIMUM_Y : MINIMUM_Y; DP(" append1 %f %f\n", cy, x - cx); - push_back(SkylineSegment(cy, x - cx)); + append(cx, cy, x - cx); } DP(" append2 %f %f\n", y, w); - push_back(SkylineSegment(y, w)); + append(x, y, w); } else if (x + w > cx) - push_back(SkylineSegment(y, x + w - cx)); + append(cx, y, x + w - cx); } //--------------------------------------------------------- diff --git a/libmscore/skyline.h b/libmscore/skyline.h index c58349a283..c05904d7fb 100644 --- a/libmscore/skyline.h +++ b/libmscore/skyline.h @@ -27,30 +27,45 @@ class Shape; //--------------------------------------------------------- struct SkylineSegment { + qreal x; qreal y; qreal w; - SkylineSegment(qreal _y, qreal _w) : y(_y), w(_w) {} + SkylineSegment(qreal _x, qreal _y, qreal _w) : x(_x), y(_y), w(_w) {} }; //--------------------------------------------------------- // SkylineLine //--------------------------------------------------------- -struct SkylineLine : public std::vector { +class SkylineLine { const bool north; + std::vector seg; + typedef std::vector::iterator SegIter; + typedef std::vector::const_iterator SegConstIter; + + SegIter insert(SegIter i, qreal x, qreal y, qreal w); + void append(qreal x, qreal y, qreal w); + SegIter find(qreal x); + SegConstIter find(qreal x) const; public: SkylineLine(bool n) : north(n) {} - void add(qreal x, qreal y, qreal w); void add(const Shape& s); void add(const QRectF& r); + void add(qreal x, qreal y, qreal w); + void clear() { seg.clear(); } void paint(QPainter&) const; void dump() const; qreal minDistance(const SkylineLine&) const; qreal max() const; bool valid(const SkylineSegment& s) const; bool isNorth() const { return north; } + + SegIter begin() { return seg.begin(); } + SegConstIter begin() const { return seg.begin(); } + SegIter end() { return seg.end(); } + SegConstIter end() const { return seg.end(); } }; //---------------------------------------------------------