Merge pull request #4768 from dmitrio95/skyline_opt2

Skylines construction optimization
This commit is contained in:
anatoly-os 2019-03-06 15:48:33 +02:00 committed by GitHub
commit fc515c4601
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 17 deletions

View file

@ -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<Fingering*> 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()));
}
}

View file

@ -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
//---------------------------------------------------------
@ -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);
}
//---------------------------------------------------------

View file

@ -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(); }
};
//---------------------------------------------------------