Skip to content

Commit

Permalink
fix musescore#11622: spacing of grace notes with ledger lines
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcSabatella committed May 27, 2014
1 parent e84a165 commit 91ed53c
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 26 deletions.
134 changes: 111 additions & 23 deletions libmscore/chord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1689,13 +1689,31 @@ void Chord::layout()

void Chord::layoutPitched()
{
for (Chord* c : _graceNotes)
c->layoutPitched();
int gi = 0;
for (Chord* c : _graceNotes) {
// HACK: graceIndex is not well-maintained on add & remove
// so rebuild now
c->setGraceIndex(gi++);
if (c->isGraceBefore())
c->layoutPitched();
}
QList<Chord*> graceNotesBefore;
int gnb = getGraceNotesBefore(&graceNotesBefore);
QList<Chord*> graceNotesAfter;
// lay out grace notes after separately so they are processed left to right
// (they are normally stored right to left)
int gna = getGraceNotesAfter(&graceNotesAfter);
if (gna) {
for (Chord* c : graceNotesAfter)
c->layoutPitched();
}

qreal _spatium = spatium();
qreal dotNoteDistance = score()->styleS(StyleIdx::dotNoteDistance).val() * _spatium;
qreal minNoteDistance = score()->styleS(StyleIdx::minNoteDistance).val() * _spatium;
qreal minTieLength = score()->styleS(StyleIdx::MinTieLength).val() * _spatium;
qreal ledgerLineLength = score()->styleD(StyleIdx::ledgerLineLength) * _spatium;
qreal graceMag = score()->styleD(StyleIdx::graceNoteMag);
qreal chordX = (_noteType == NoteType::NORMAL) ? ipos().x() : 0.0;

while (_ledgerLines) {
Expand All @@ -1706,6 +1724,7 @@ void Chord::layoutPitched()

qreal lll = 0.0; // space to leave at left of chord
qreal rrr = 0.0; // space to leave at right of chord
qreal lhead = 0.0; // amount of notehead to left of chord origin
Note* upnote = upNote();

delete _tabDur; // no TAB? no duration symbol! (may happen when converting a TAB into PITCHED)
Expand Down Expand Up @@ -1740,6 +1759,8 @@ void Chord::layoutPitched()
qreal x2 = x1 + note->headWidth();
lll = qMax(lll, -x1);
rrr = qMax(rrr, x2);
// track amount of space due to notehead only
lhead = qMax(lhead, -x1);

Accidental* accidental = note->accidental();
if (accidental) {
Expand Down Expand Up @@ -1856,27 +1877,97 @@ void Chord::layoutPitched()

if (_ledgerLines) {

// increase distance to previous chord if both have
// ledger lines
// we may need to increase distance to previous chord
Chord* pc = 0;

if (_noteType == NOTE_NORMAL) {
// normal note
if (gnb) {
// if there are grace notes before, get last
pc = graceNotesBefore.last();
}
else if (rtick()) {
// if this is not first chord of measure, get previous chord
Segment* s = segment()->prev(Segment::SegChordRest);
if (s && s->element(track()) && s->element(track())->type() == CHORD)
pc = static_cast<Chord*>(s->element(track()));
}
if (pc && !pc->graceNotes().isEmpty()) {
// if previous chord has grace notes after, find last one
// which, conveniently, is stored first
for (Chord* c : pc->graceNotes()) {
if (c->isGraceAfter()) {
pc = c;
break;
}
}
}
}

else {
// grace note
Chord* mainChord = static_cast<Chord*>(parent());
bool before = isGraceBefore();
int incIdx = before ? -1 : 1;
int endIdx = before ? -1 : mainChord->graceNotes().size();
// find previous grace note of same type
for (int i = _graceIndex + incIdx; i != endIdx; i += incIdx) {
Chord* pgc = mainChord->graceNotes().at(i);
if (pgc->isGraceBefore() == before) {
pc = pgc;
break;
}
}
if (!pc) {
// no previous grace note found
if (!before){
// grace note after - use main note
pc = mainChord;
}
else if (mainChord->rtick()) {
// grace note before - use previous normal note of measure
Segment* s = mainChord->segment()->prev(Segment::SegChordRest);
if (s && s->element(track()) && s->element(track())->type() == CHORD)
pc = static_cast<Chord*>(s->element(track()));
}
}
}

Segment* s = segment();
s = s->prev(Segment::SegChordRest);
if (s && s->element(track()) && s->element(track())->type() == ElementType::CHORD
&& static_cast<Chord*>(s->element(track()))->ledgerLines()) {
// TODO: detect case where one chord is above staff, the other below
lll = qMax(_spatium * 0.8f, lll);
if (pc) {
// previous chord found
qreal llsp = 0.0;
int pUpLine = pc->upNote()->line();
int pDownLine = pc->downNote()->line();
int upLine = upNote()->line();
int downLine = downNote()->line();
int ledgerBelow = staff()->lines() * 2;
if (pc->_ledgerLines && ((pUpLine < 0 && upLine < 0) || (pDownLine >= ledgerBelow && downLine >= ledgerBelow))) {
// both chords have ledger lines above or below staff
llsp = ledgerLineLength;
// add space between ledger lines
llsp += _spatium * 0.2 * pc->mag();
// if any portion of note extended to left of origin
// we need to include that here so it is not subsumed by ledger line
llsp += lhead;
}
else if (pc->up() && upLine < 0) {
// even if no ledger lines in previous chord,
// we may need a little space to avoid crossing stem
llsp = ledgerLineLength * 0.5;
llsp += _spatium * 0.2 * pc->mag();
llsp += lhead;
}
lll = qMax(llsp, lll);
}

}

_space.setLw(lll);
_space.setRw(rrr);

QList<Chord*> graceNotesBefore;
qreal graceMag = score()->styleD(StyleIdx::graceNoteMag);
int nb = getGraceNotesBefore(&graceNotesBefore);
if (nb){
if (gnb){
qreal xl = -(_space.lw() + minNoteDistance) - chordX;
for (int i = nb-1; i >= 0; --i) {
for (int i = gnb-1; i >= 0; --i) {
Chord* c = graceNotesBefore.value(i);
xl -= c->space().rw()/* * 1.2*/;
c->setPos(xl, 0);
Expand All @@ -1885,10 +1976,7 @@ void Chord::layoutPitched()
if (-xl > _space.lw())
_space.setLw(-xl);
}
QList<Chord*> graceNotesAfter;
getGraceNotesAfter(&graceNotesAfter);
int na = graceNotesAfter.size();
if (na){
if (gna){
// get factor for start distance after main note. Values found by testing.
qreal fc;
switch (durationType().type()) {
Expand All @@ -1902,7 +1990,7 @@ void Chord::layoutPitched()
default: fc = 1;
}
qreal xr = fc * (_space.rw() + minNoteDistance);
for (int i = 0; i <= na - 1; i++) {
for (int i = 0; i <= gna - 1; i++) {
Chord* c = graceNotesAfter.value(i);
xr += c->space().lw() * (i == 0 ? 1.3 : 1);
c->setPos(xr, 0);
Expand Down Expand Up @@ -2638,7 +2726,7 @@ Measure* Chord::measure() const
int Chord::getGraceNotesBefore(QList<Chord*>* graceNotesBefore)
{
int i = 0;
foreach (Chord* c, _graceNotes){
foreach (Chord* c, _graceNotes) {
if (c->noteType() == NoteType::ACCIACCATURA
|| c->noteType() == NoteType::APPOGGIATURA
|| c->noteType() == NoteType::GRACE4
Expand All @@ -2658,10 +2746,10 @@ int Chord::getGraceNotesBefore(QList<Chord*>* graceNotesBefore)

int Chord::getGraceNotesAfter(QList<Chord*>* graceNotesAfter)
{
if(_graceNotes.length() == 0)
if (_graceNotes.length() == 0)
return 0;
int i = 0;
for(int j = _graceNotes.length() - 1; j >= 0; --j){
for (int j = _graceNotes.length() - 1; j >= 0; --j) {
Chord* c = _graceNotes.at(j);
if (c->noteType() == NoteType::GRACE8_AFTER
|| c->noteType() == NoteType::GRACE16_AFTER
Expand Down
2 changes: 1 addition & 1 deletion mscore/actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ Shortcut Shortcut::sc[] = {
"grace8after",
QT_TRANSLATE_NOOP("action","Grace: 8th after"),
QT_TRANSLATE_NOOP("action","Add 8th grace note after"),
QT_TRANSLATE_NOOP("action","Grace: quarter"),
QT_TRANSLATE_NOOP("action","Grace: 8th after"),
grace8after_ICON
),
Shortcut(
Expand Down
2 changes: 1 addition & 1 deletion vtest/gen
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ else
chord-layout-7 chord-layout-8 chord-layout-9 chord-layout-10 chord-layout-11 chord-layout-12\
accidental-1 accidental-2 accidental-3 accidental-4\
accidental-5 accidental-6 accidental-7 accidental-8\
tie-1 grace-1 grace-2 harmony-1 beams-1 beams-2 user-offset-1 user-offset-2"
tie-1 grace-1 grace-2 grace-3 harmony-1 beams-1 beams-2 user-offset-1 user-offset-2"
fi

DPI=130
Expand Down
2 changes: 1 addition & 1 deletion vtest/gen.bat
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ set SRC=mmrest-1,bravura-mmrest,mmrest-2,mmrest-4,mmrest-5,mmrest-6,mmrest-7,mmr
chord-layout-7,chord-layout-8,chord-layout-9,chord-layout-10,chord-layout-11,chord-layout-12, ^
accidental-1,accidental-2,accidental-3,accidental-4, ^
accidental-5,accidental-6,accidental-7,accidental-8, ^
tie-1,grace-1,grace-2,harmony-1,beams-1,beams-2,user-offset-1,user-offset-2
tie-1,grace-1,grace-2,grace-3,harmony-1,beams-1,beams-2,user-offset-1,user-offset-2

set MSCORE=..\win32install\bin\mscore.exe
set DPI=130
Expand Down
Binary file added vtest/grace-3-ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added vtest/grace-3.mscz
Binary file not shown.

0 comments on commit 91ed53c

Please sign in to comment.