Skip to content

Commit

Permalink
More beautiful default layout related to single-note tremolos
Browse files Browse the repository at this point in the history
fix #20390: tremolo through stem collide with ledger lines
  • Loading branch information
Harmoniker1 committed Jan 25, 2020
1 parent 17d6e06 commit ffd2ed1
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 98 deletions.
51 changes: 16 additions & 35 deletions libmscore/chord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1403,35 +1403,6 @@ qreal Chord::defaultStemLength() const
}
}

// adjust stem len for tremolo
if (_tremolo && !_tremolo->twoNotes() && !_tremolo->placeMidStem()) {
// Use the old algorithm for stem lengthening. It not always
// optimal but still performs better when not placing the tremolo
// at stem middle. TODO: rework minAbsStemLen() to perform
// correctly in this case too.

// hook up odd lines
static const int tab1[2][2][2][4] = {
{ { { 0, 0, 0, 1 }, // stem - down - even - lines
{ 0, 0, 0, 2 } // stem - down - odd - lines
},
{ { 0, 0, 0, -1 }, // stem - up - even - lines
{ 0, 0, 0, -2 } // stem - up - odd - lines
}
},
{ { { 0, 0, 1, 2 }, // hook - down - even - lines
{ 0, 0, 1, 2 } // hook - down - odd - lines
},
{ { 0, 0, -1, -2 }, // hook - up - even - lines
{ 0, 0, -1, -2 } // hook - up - odd - lines
}
}
};
int odd = (up() ? upLine() : downLine()) & 1;
int n = tab1[hookIdx ? 1 : 0][up() ? 1 : 0][odd][_tremolo->lines()-1];
stemLen += n * .5;
}

if (tab)
stemLen *= lineDistance;

Expand All @@ -1446,21 +1417,31 @@ qreal Chord::defaultStemLength() const

//---------------------------------------------------------
// minAbsStemLength
// get minimum stem length with tremolo
//---------------------------------------------------------

qreal Chord::minAbsStemLength() const
{
if (!_tremolo || _tremolo->twoNotes() || !_tremolo->placeMidStem())
if (!_tremolo || _tremolo->twoNotes())
return 0.0;

_tremolo->layout(); // guarantee right "height value"

qreal height;
if (up())
height = downPos() - _tremolo->pos().y();
else
height = _tremolo->pos().y() + _tremolo->height() - upPos();

int beamLvl = beams();
const bool hasHook = (beamLvl > 0) && !beam();
const bool hasHook = beamLvl && !beam();
if (hasHook)
++beamLvl; // reserve more space for stem with both hook and tremolo
const qreal beamDist = beam() ? beam()->beamDist() : (0.5 * spatium());
const qreal tremoloSpacing = 0.5 * spatium(); // TODO: style setting
beamLvl += (up() ? 4.0 : 2.5); // reserve more space for stem with both hook and tremolo
const qreal sw = score()->styleS(Sid::tremoloStrokeWidth).val();
const qreal beamDist = beam() ? beam()->beamDist() : (sw * spatium());
const qreal additionalHeight = beamLvl ? 0 : sw * spatium();

return beamLvl * beamDist + _tremolo->height() + 2 * tremoloSpacing;
return height + beamLvl * beamDist + additionalHeight;
}

//---------------------------------------------------------
Expand Down
94 changes: 31 additions & 63 deletions libmscore/tremolo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "tremolo.h"
#include "score.h"
#include "staff.h"
#include "style.h"
#include "chord.h"
#include "note.h"
Expand Down Expand Up @@ -234,71 +235,38 @@ void Tremolo::layoutOneNoteTremolo(qreal x, qreal y, qreal _spatium)
{
Q_ASSERT(!twoNotes());

bool up = _chord1->up();
int line = up ? _chord1->upLine() : _chord1->downLine();
bool up = chord()->up();
int line = up ? chord()->upLine() : chord()->downLine();

if (!placeMidStem()) {
static const qreal t[3][2][4][2] = {
// normal stem
{
// DOWN
{
// even line odd line
{ 6, 5 }, // line 1
{ 6 - 2 * .8, 5 - 2 * .8 }, // line 2
{ 6 - 4 * .8, 3 }, // line 3
{ 2 , 3 } // line 4
},
// UP
{
// even line odd line
{ -6, -5 }, // line 1
{ -6, -5 }, // line 2
{ -6, -3 - 4 * .8 }, // line 3
{ -2 - 6 * .8, -3 - 6 * .8 } // line 4
}
},
// stem with hook
{
// DOWN
{
// even line odd line
{ 3, 3 }, // line 1
{ 2, 2 }, // line 2
{ 2, 2 }, // line 3
{ 2, 2 } // line 4
},
// UP
{
// even line odd line
{ -3, -3 }, // line 1
{ -2 - 2 * .8, -2 - 2 * .8 }, // line 2
{ -2 - 4 * .8, -2 - 4 * .8 }, // line 3
{ -2 - 6 * .8, -2 - 6 * .8 } // line 4
}
},
// stem with beam
{
// DOWN
{
// even line odd line
{ 3, 3 }, // line 1
{ 2, 2 }, // line 2
{ 2, 2 }, // line 3
{ 2, 2 } // line 4
},
// UP
{
// even line odd line
{ -3, -3 }, // line 1
{ -2 - 2 * .8, -2 - 2 * .8 }, // line 2
{ -2 - 4 * .8, -2 - 4 * .8 }, // line 3
{ -2 - 6 * .8, -2 - 6 * .8 } // line 4
}
},
};
int idx = _chord1->hook() ? 1 : (_chord1->beam() ? 2 : 0);
y = (line + t[idx][up][_lines-1][line & 1]) * .5 * _spatium;
const qreal td = score()->styleS(Sid::tremoloDistance).val();
const qreal sw = score()->styleS(Sid::tremoloStrokeWidth).val();

qreal t;
// nearest distance between note and tremolo stroke should be no less than 3
if (chord()->hook() || chord()->beam()) {
t = up ? -3.0 - (2.0 * (lines() - 1)) * td - 2.0 * sw : 3.0;
}
else {
if (!up && !(line & 1)) // stem is down; even line
t = qMax(6.0 - (2.0 * (lines() - 1)) * td - 2.0 * sw, 3.0);
else if (!up && (line & 1)) // stem is down; odd line
t = qMax(5.0 - (2.0 * (lines() - 1)) * td - 2.0 * sw, 3.0);
else if ( up && !(line & 1)) // stem is up; even line
t = qMin(-3.0 - (2.0 * (lines() - 1)) * td - 2.0 * sw, -6.0);
else if ( up && (line & 1)) // stem is up; odd line
t = qMin(-3.0 - (2.0 * (lines() - 1)) * td - 2.0 * sw, -5.0);
}

qreal yLine = line + t;
// prevent stroke from going out of staff at the top while stem direction is down
if (!chord()->up())
yLine = qMax(yLine, 0.0);
// prevent stroke from going out of staff at the bottom while stem direction is up
else
yLine = qMin(yLine, (staff()->lines(tick()) - 1) * 2 - (2.0 * (lines() - 1)) * td - 2.0 * sw);

y = yLine * .5 * _spatium;
}
else {
const Note* n = up ? chord()->downNote() : chord()->upNote();
Expand Down

0 comments on commit ffd2ed1

Please sign in to comment.