Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skylines construction optimization #4768

Merged
merged 2 commits into from
Mar 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions libmscore/layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3508,6 +3508,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()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, could be worth also adding a check for mno->autoplace() before adding to the skyline. It's one of the few such things I didn't do in my PR #4730. I figure I'll need to update that anyhow if this gets merged first, though.

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;
Expand Down Expand Up @@ -3535,7 +3538,6 @@ void Score::layoutSystemElements(System* system, LayoutContext& lc)
}
for (auto n : c->notes())
notes.push_back(n);
std::list<Fingering*> fingerings;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, thanks!

for (Note* note : notes) {
for (Element* e : note->el()) {
if (e->isFingering()) {
Expand All @@ -3562,10 +3564,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()));
}
}

Expand Down
60 changes: 51 additions & 9 deletions libmscore/skyline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<SkylineLine*>(this)->find(x);
}

//---------------------------------------------------------
// add
//---------------------------------------------------------
Expand Down Expand Up @@ -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;
Expand All @@ -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 {
Expand All @@ -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;
}
Expand All @@ -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
Expand All @@ -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;
Expand All @@ -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);
}

//---------------------------------------------------------
Expand Down
21 changes: 18 additions & 3 deletions libmscore/skyline.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<SkylineSegment> {
class SkylineLine {
const bool north;
std::vector<SkylineSegment> seg;
typedef std::vector<SkylineSegment>::iterator SegIter;
typedef std::vector<SkylineSegment>::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(); }
};

//---------------------------------------------------------
Expand Down