Skip to content

Commit

Permalink
Fix #281639: Better handling of Clefs and Bar Lines on cutaway and os…
Browse files Browse the repository at this point in the history
…sia | collect_artifacts
  • Loading branch information
elerouxx committed Sep 15, 2020
1 parent 31b0c0b commit 6c45bf6
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 8 deletions.
10 changes: 7 additions & 3 deletions libmscore/barline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,13 @@ int nextVisibleSpannedStaff(const BarLine* bl)
int nstaves = score->nstaves();
int staffIdx = bl->staffIdx();
Segment* segment = bl->segment();
for (int i = staffIdx + 1; i < nstaves; ++i) {
Measure* nm = bl->measure()->nextMeasure();
for (int i = staffIdx + 1; i < nstaves; ++i) {
Staff* s = score->staff(i);
if (s->part()->show() && bl->measure()->visible(i))
if (s->part()->show() && (bl->measure()->visible(i) || // span bar line if measure is visible
(segment && segment->isEndBarLineType() && // or if this is a measure's End Bar Line and...
((nm ? nm->visible(i) : false) && (nm ? nm->system() == bl->measure()->system() : false) // ...next measure is visible in system
|| bl->measure()->isCourtesyClef(i))))) // ...or measure has Courtesy Clef
return i;
BarLine* nbl = toBarLine(segment->element(i * VOICES));
if (!nbl || !nbl->spanStaff())
Expand Down Expand Up @@ -1151,7 +1155,7 @@ void BarLine::endEditDrag(EditData& ed)
newSpanTo = 0;
}

bool localDrag = ed.control() || segment()->isBarLine();
bool localDrag = ed.control() || segment()->isBarLineType();
if (localDrag) {
Segment* s = segment();
for (int staffIdx = staffIdx1; staffIdx < staffIdx2; ++staffIdx) {
Expand Down
49 changes: 45 additions & 4 deletions libmscore/measure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,16 @@ Measure::Measure(const Measure& m)

void Measure::layoutStaffLines()
{
for (MStaff* ms : _mstaves)
ms->lines()->layout();
int staffIdx = 0;
for (MStaff* ms : _mstaves) {
if (isCourtesyClef(staffIdx) && (score()->staff(staffIdx)->cutaway() || !visible(staffIdx)))
// short staff lines for a courtesy clef on a hidden measure
ms->lines()->layoutPartialWidth(width(), 4.0 ,false);
else
// normal staff lines
ms->lines()->layout();
staffIdx += 1;
}
}

//---------------------------------------------------------
Expand Down Expand Up @@ -2505,16 +2513,18 @@ void Measure::scanElements(void* data, void (*func)(void*, Element*), bool all)

int nstaves = score()->nstaves();
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
if (!all && !(visible(staffIdx) && score()->staff(staffIdx)->show()))
if (!all && !score()->staff(staffIdx)->show())
continue;
MStaff* ms = _mstaves[staffIdx];
func(data, ms->lines());
// show spacers and measure number even on invisible measures
if (ms->vspacerUp())
func(data, ms->vspacerUp());
if (ms->vspacerDown())
func(data, ms->vspacerDown());
if (ms->noText())
func(data, ms->noText());
if (visible(staffIdx) || isCourtesyClef(staffIdx))
func(data, ms->lines());
}

for (Segment* s = first(); s; s = s->next()) {
Expand Down Expand Up @@ -2768,6 +2778,37 @@ bool Measure::isEmpty(int staffIdx) const
return true;
}

//---------------------------------------------------------
// isCourtesyClef
// Check for empty measure with only
// a Courtesy Clef before the End Bar Line
//---------------------------------------------------------

bool Measure::isCourtesyClef(int staffIdx) const
{
if (!isEmpty(staffIdx))
return false;
int strack;
int etrack;
if (staffIdx < 0) {
strack = 0;
etrack = score()->nstaves() * VOICES;
}
else {
strack = staffIdx * VOICES;
etrack = strack + VOICES;
}
Segment* s = last()->prev();
if (!s)
return false;
for (int track = strack; track < etrack; ++track) {
Element* e = s->element(track);
if (e && e->isClef() && toClef(e)->showCourtesy())
return true;
}
return false;
}

//---------------------------------------------------------
// isFullMeasureRest
// Check for an empty measure, filled with full measure
Expand Down
1 change: 1 addition & 0 deletions libmscore/measure.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ class Measure final : public MeasureBase {
void checkMultiVoices(int staffIdx);
bool hasVoice(int track) const;
bool isEmpty(int staffIdx) const;
bool isCourtesyClef(int staffIdx) const;
bool isFullMeasureRest() const;
bool isRepeatMeasure(const Staff* staff) const;
bool visible(int staffIdx) const;
Expand Down
18 changes: 17 additions & 1 deletion libmscore/segment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1137,13 +1137,29 @@ void Segment::scanElements(void* data, void (*func)(void*, Element*), bool all)
{
for (int track = 0; track < score()->nstaves() * VOICES; ++track) {
int staffIdx = track/VOICES;
if (!all && !(measure()->visible(staffIdx) && score()->staff(staffIdx)->show())) {
if (!all && !(/*measure()->visible(staffIdx) &&*/ score()->staff(staffIdx)->show())) {
track += VOICES - 1;
continue;
}
Element* e = element(track);
if (e == 0)
continue;
// if measure is not visible, handle visible End Bar Lines and Courtesy Clefs in certain conditions (for ossias and cutaway):
if (!measure()->visible(staffIdx)) {
if (isEndBarLineType()) {
if (!measure()->nextMeasure())
continue; // skip EndBarLines if next measure == NULL
else if (!measure()->isCourtesyClef(staffIdx) &&
!(measure()->nextMeasure()->visible(staffIdx) && measure()->nextMeasure()->system() == measure()->system()))
continue; // skip if not on courtesy clef measures and if next measure in system is not visible
}
else if (isClefType()) {
if (!measure()->isCourtesyClef(staffIdx))
continue; // skip clefs except for courtesy clefs at the end of invisible measures
}
else
continue;
}
e->scanElements(data, func, all);
}
for (Element* e : annotations()) {
Expand Down
45 changes: 45 additions & 0 deletions libmscore/stafflines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,51 @@ void StaffLines::layoutForWidth(qreal w)
}
}

//---------------------------------------------------------
// layoutPartialWidth
//---------------------------------------------------------

void StaffLines::layoutPartialWidth(qreal w, qreal wPartial, bool alignLeft)
{
const Staff* s = staff();
qreal _spatium = spatium();
wPartial *= spatium();
qreal dist = _spatium;
setPos(QPointF(0.0, 0.0));
int _lines;
if (s) {
setMag(s->mag(measure()->tick()));
setColor(s->color());
const StaffType* st = s->staffType(measure()->tick());
dist *= st->lineDistance().val();
_lines = st->lines();
rypos() = st->yoffset().val() * _spatium;
}
else {
_lines = 5;
setColor(MScore::defaultColor);
}
lw = score()->styleS(Sid::staffLineWidth).val() * _spatium;
qreal x1 = pos().x();
qreal x2 = x1 + w;
qreal y = pos().y();
bbox().setRect(x1, -lw * .5 + y, w, (_lines-1) * dist + lw);

if (_lines == 1) {
qreal extraSize = _spatium;
bbox().adjust(0, -extraSize, 0, extraSize);
}

lines.clear();
for (int i = 0; i < _lines; ++i) {
if (alignLeft)
lines.push_back(QLineF(x1, y, x1 + wPartial, y));
else
lines.push_back(QLineF(x2-wPartial, y, x2, y));
y += dist;
}
}

//---------------------------------------------------------
// draw
//---------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions libmscore/stafflines.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class StaffLines final : public Element {
Measure* measure() const { return (Measure*)parent(); }
qreal y1() const;
void layoutForWidth(qreal width);
void layoutPartialWidth(qreal w, qreal wPartial, bool alignLeft);
};

} // namespace Ms
Expand Down

0 comments on commit 6c45bf6

Please sign in to comment.