Skip to content
Browse files

Fix #69846, #69821, #63561 - multi-voice TAB's: stem and slur positions


In the original TAB implementation, the "Stems above / below" setting was followed when there was only one voice, while with multiple voices, voice 1 stems were always above and voice 2 stems always below.

In issue the OP reported that:
- with multiple voices, stems in TAB did not follow the "Stems above / below" setting;
- extra space was allocated for voice 2 stems.

Both issues were more apparent than real, because the example provided casually had no stems in voice 2 (all whole notes). With the commit 33797cd :
- voice 1 stems are forced to be below or down according to the setting even for multi-voice cases and voice 2 stems on the opposite side;
- additional distance is allocated above the TAB staff (but not below) if stems are above or there are multiple voices or below (but not above) if stems are below and there is only voice 1.


1a) The original stem directions were __by design__, assuming that with multiple voices notes of voice 1 tend to be above and notes of voice 2 tend to be below; then it is more sensible to put voice 1 stems above and voice 2 stems below, limiting the "Stems above / below" setting to the single voice case only.

1b) Stem direction controls slurs and tie placement and users are complaining that, with multiple voices, stems, slurs and ties are placed unexpectedly. See issue and forum post .

2) About additional staff distance allocation, with multiple voices it has to be allocated __both__ above and below, as stems may appear both above and below.


1) This patch fixes 1) by restoring the original stem direction computation (single voice: follow "Stems above / below" setting | multiple voices: voice 1 unconditionally above and voice 2 below) when tab is configured to have stems beside the staff and also when it is configured to have __no stems at all_ (so that slurs and ties occur in expected positions).

2) It corrects additional staff distance allocation for the multiple voice case. No resources are spent to check the odd case when one voice casually has no stems over the entire system (in which case, additional distance on that side could in theory be spared).
  • Loading branch information...
mgavioli authored and lasconic committed Jul 26, 2015
1 parent 8b2cfbf commit 030b958af2494269abf27cd406a99f7ae585a992
Showing with 13 additions and 6 deletions.
  1. +5 −4 libmscore/chord.cpp
  2. +8 −2 libmscore/measure.cpp
@@ -811,12 +811,13 @@ void Chord::computeUp()
// if no stems or stem beside staves
if (tab->slashStyle() || !tab->stemThrough()) {
// if measure has voices, set stem direction according to voice
// reverse the logic if stemsDown (#63561)
if (measure()->mstaff(staffIdx())->hasVoices)
_up = !tab->stemsDown() ? !(track() % 2) : (track() % 2);
_up = !(track() % 2);
else // if only voice 1,
_up = !tab->stemsDown();// unconditionally set _up according to TAB stem direction
return; // (if no stems, _up does not really matter!)
// uncondtionally set to down if not stems or according to TAB stem direction otherwise
// (even with no stems, stem direction controls position of slurs and ties)
_up = tab->slashStyle() ? false : !tab->stemsDown();
// if TAB has stems through staves, chain into standard processing
@@ -3537,10 +3537,16 @@ void Measure::layoutX(qreal stretch)
if (stt->slashStyle()) // if no stems
distAbove = stt->genDurations() ? -stt->durationBoxY() : 0.0;
else { // if stems
if (stt->stemsDown() && !mstaff(staffIdx)->hasVoices)
if (mstaff(staffIdx)->hasVoices) { // reserve space both above and below
else { // if no voices, reserve space on stem side
if (stt->stemsDown())
if (distAbove > staves[staffIdx]->distanceUp)
staves[staffIdx]->distanceUp = distAbove;

0 comments on commit 030b958

Please sign in to comment.
You can’t perform that action at this time.