@@ -1466,6 +1466,7 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
14661466 const track_idx_t startTrack = staffIdx * VOICES;
14671467 const track_idx_t endTrack = startTrack + VOICES;
14681468 const Fraction tick = segment->tick ();
1469+ const StaffType* staffType = staff->staffType (segment->tick ());
14691470
14701471 // we need to check all the notes in all the staves of the part so that we don't get weird collisions
14711472 // between accidentals etc with moved notes
@@ -1487,7 +1488,7 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
14871488 std::vector<Note*> downStemNotes;
14881489 int upVoices = 0 ;
14891490 int downVoices = 0 ;
1490- double nominalWidth = ctx.conf ().noteHeadWidth () * staff->staffMag (tick);
1491+ double nominalWidth = !isTab ? ctx.conf ().noteHeadWidth () * staff->staffMag (tick) : ctx. conf (). fretWidth (staffType );
14911492 double maxUpWidth = 0.0 ;
14921493 double maxDownWidth = 0.0 ;
14931494 double maxUpMag = 0.0 ;
@@ -1542,7 +1543,7 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
15421543 }
15431544 }
15441545
1545- if (upVoices + downVoices && !isTab ) {
1546+ if (upVoices + downVoices && staffType-> stemThrough () ) {
15461547 // TODO: use track as secondary sort criteria?
15471548 // otherwise there might be issues with unisons between voices
15481549 // in some corner cases
@@ -1553,7 +1554,7 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
15531554 // layout upstem noteheads
15541555 if (upVoices > 1 ) {
15551556 std::sort (upStemNotes.begin (), upStemNotes.end (),
1556- [](Note* n1, const Note* n2) ->bool { return n1->line () > n2->line (); });
1557+ [](Note* n1, const Note* n2) ->bool { return n1->stringOrLine () > n2->stringOrLine (); });
15571558 }
15581559 if (upVoices) {
15591560 double hw = layoutChords2 (upStemNotes, true , ctx);
@@ -1563,7 +1564,7 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
15631564 // layout downstem noteheads
15641565 if (downVoices > 1 ) {
15651566 std::sort (downStemNotes.begin (), downStemNotes.end (),
1566- [](Note* n1, const Note* n2) ->bool { return n1->line () > n2->line (); });
1567+ [](Note* n1, const Note* n2) ->bool { return n1->stringOrLine () > n2->stringOrLine (); });
15671568 }
15681569 if (downVoices) {
15691570 double hw = layoutChords2 (downStemNotes, false , ctx);
@@ -1640,7 +1641,7 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
16401641 if (upVoices && downVoices) {
16411642 Note* bottomUpNote = upStemNotes.front ();
16421643 Note* topDownNote = downStemNotes.back ();
1643- int separation = topDownNote->line () - bottomUpNote->line ();
1644+ int separation = topDownNote->stringOrLine () - bottomUpNote->stringOrLine ();
16441645
16451646 std::vector<Note*> overlapNotes;
16461647 overlapNotes.reserve (8 );
@@ -1666,21 +1667,21 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
16661667
16671668 // build list of overlapping notes
16681669 for (size_t i = 0 , n = upStemNotes.size (); i < n; ++i) {
1669- if (upStemNotes[i]->line () >= topDownNote->line () - 1 ) {
1670+ if (upStemNotes[i]->stringOrLine () >= topDownNote->stringOrLine () - 1 ) {
16701671 overlapNotes.push_back (upStemNotes[i]);
16711672 } else {
16721673 break ;
16731674 }
16741675 }
16751676 for (size_t i = downStemNotes.size (); i > 0 ; --i) { // loop most probably needs to be in this reverse order
1676- if (downStemNotes[i - 1 ]->line () <= bottomUpNote->line () + 1 ) {
1677+ if (downStemNotes[i - 1 ]->stringOrLine () <= bottomUpNote->stringOrLine () + 1 ) {
16771678 overlapNotes.push_back (downStemNotes[i - 1 ]);
16781679 } else {
16791680 break ;
16801681 }
16811682 }
16821683 std::sort (overlapNotes.begin (), overlapNotes.end (),
1683- [](Note* n1, const Note* n2) ->bool { return n1->line () > n2->line (); });
1684+ [](Note* n1, const Note* n2) ->bool { return n1->stringOrLine () > n2->stringOrLine (); });
16841685
16851686 // determine nature of overlap
16861687 bool shareHeads = true ; // can all overlapping notes share heads?
@@ -1704,7 +1705,7 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
17041705 continue ;
17051706 }
17061707 }
1707- int line = n->line ();
1708+ int line = n->stringOrLine ();
17081709 int d = lastLine - line;
17091710 switch (d) {
17101711 case 0 :
@@ -1776,8 +1777,8 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
17761777 int topDownStemLen = 0 ;
17771778 if (!conflictUnison && topDownNote->chord ()->stem ()) {
17781779 topDownStemLen = std::round (topDownNote->chord ()->stem ()->ldata ()->bbox ().height () / sp * 2 );
1779- if (bottomUpNote->line () > firstLedgerBelow - 1 && topDownNote->line () < bottomUpNote->line ()
1780- && topDownNote->line () + topDownStemLen >= firstLedgerBelow) {
1780+ if (bottomUpNote->stringOrLine () > firstLedgerBelow - 1 && topDownNote->stringOrLine () < bottomUpNote->stringOrLine ()
1781+ && topDownNote->stringOrLine () + topDownStemLen >= firstLedgerBelow) {
17811782 ledgerOverlapBelow = true ;
17821783 }
17831784 }
@@ -1786,8 +1787,8 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
17861787 int bottomUpStemLen = 0 ;
17871788 if (!conflictUnison && bottomUpNote->chord ()->stem ()) {
17881789 bottomUpStemLen = std::round (bottomUpNote->chord ()->stem ()->ldata ()->bbox ().height () / sp * 2 );
1789- if (topDownNote->line () < -1 && topDownNote->line () < bottomUpNote->line ()
1790- && bottomUpNote->line () - bottomUpStemLen <= firstLedgerAbove) {
1790+ if (topDownNote->stringOrLine () < -1 && topDownNote->stringOrLine () < bottomUpNote->stringOrLine ()
1791+ && bottomUpNote->stringOrLine () - bottomUpStemLen <= firstLedgerAbove) {
17911792 ledgerOverlapAbove = true ;
17921793 }
17931794 }
@@ -1841,8 +1842,8 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
18411842 } else {
18421843 // Prevent ledger line & notehead collision
18431844 double adjSpace
1844- = (topDownNote->line () <= firstLedgerAbove
1845- || bottomUpNote->line () >= firstLedgerBelow) ? ledgerLen - ledgerGap - 0.2 * sp : -0.2 * sp;
1845+ = (topDownNote->stringOrLine () <= firstLedgerAbove
1846+ || bottomUpNote->stringOrLine () >= firstLedgerBelow) ? ledgerLen - ledgerGap - 0.2 * sp : -0.2 * sp;
18461847 upOffset = maxDownWidth + adjSpace;
18471848 if (downHooks) {
18481849 bool needsHookSpace = (ledgerOverlapBelow || ledgerOverlapAbove);
@@ -1854,21 +1855,23 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
18541855 } else {
18551856 // no direct conflict, so parts can overlap (downstem on left)
18561857 // just be sure that stems clear opposing noteheads and ledger lines
1857- double clearLeft = 0.0 , clearRight = 0.0 ;
1858+ // Stems are in the middle of fret marks on TAB staves
1859+ double clearLeft = isTab ? bottomUpNote->chord ()->stemPosX () : 0.0 ;
1860+ double clearRight = isTab ? bottomUpNote->chord ()->stemPosX () : 0.0 ;
18581861 if (topDownNote->chord ()->stem ()) {
18591862 if (ledgerOverlapBelow) {
18601863 // Create space between stem and ledger line below staff
1861- clearLeft = ledgerLen + ledgerGap + topDownNote->chord ()->stem ()->lineWidth ();
1864+ clearLeft + = ledgerLen + ledgerGap + topDownNote->chord ()->stem ()->lineWidth ();
18621865 } else {
1863- clearLeft = topDownNote->chord ()->stem ()->lineWidth () + 0.3 * sp;
1866+ clearLeft + = topDownNote->chord ()->stem ()->lineWidth () + 0.3 * sp;
18641867 }
18651868 }
18661869 if (bottomUpNote->chord ()->stem ()) {
18671870 if (ledgerOverlapAbove) {
18681871 // Create space between stem and ledger line above staff
1869- clearRight = maxDownWidth + ledgerLen + ledgerGap - maxUpWidth + bottomUpNote->chord ()->stem ()->lineWidth ();
1872+ clearRight + = maxDownWidth + ledgerLen + ledgerGap - maxUpWidth + bottomUpNote->chord ()->stem ()->lineWidth ();
18701873 } else {
1871- clearRight = bottomUpNote->chord ()->stem ()->lineWidth () + std::max (maxDownWidth - maxUpWidth, 0.0 ) + 0.3 * sp;
1874+ clearRight + = bottomUpNote->chord ()->stem ()->lineWidth () + std::max (maxDownWidth - maxUpWidth, 0.0 ) + 0.3 * sp;
18721875 }
18731876 } else {
18741877 downDots = 0 ; // no need to adjust for dots in this case
@@ -1878,15 +1881,18 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
18781881 Note* topUpNote = upStemNotes.back ();
18791882 // Move notes out of the way of straight flags
18801883 int pad = ctx.conf ().styleB (Sid::useStraightNoteFlags) ? 2 : 1 ;
1881- bool overlapsFlag = topDownNote->line () + topDownStemLen + pad > topUpNote->line ();
1884+ bool overlapsFlag = topDownNote->stringOrLine () + topDownStemLen + pad > topUpNote->stringOrLine ();
18821885 if (downHooks && (ledgerOverlapBelow || overlapsFlag)) {
18831886 // we will need more space to avoid collision with hook
18841887 // but we won't need as much dot adjustment
1888+ Hook* hook = topDownNote->chord ()->hook ();
1889+ double hookWidth = hook ? hook->width () : 0.0 ;
18851890 if (ledgerOverlapBelow) {
1886- Hook* hook = topDownNote->chord ()->hook ();
1887- double hookWidth = hook ? hook->width () : 0.0 ;
18881891 upOffset = hookWidth + ledgerLen + ledgerGap;
18891892 }
1893+ if (isTab) {
1894+ upOffset = hookWidth + maxDownWidth;
1895+ }
18901896 upOffset = std::max (upOffset, maxDownWidth + 0.1 * sp);
18911897 dotAdjustThreshold = maxUpWidth - 0.3 * sp;
18921898 }
@@ -1937,6 +1943,7 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
19371943 Chord::LayoutData* chordLdata = chord->mutldata ();
19381944 if (chord->up ()) {
19391945 if (!muse::RealIsNull (upOffset)) {
1946+ oversizeUp = isTab ? oversizeUp / 2 : oversizeUp;
19401947 chordLdata->moveX (upOffset + centerAdjustUp + oversizeUp);
19411948 if (downDots && !upDots) {
19421949 chordLdata->moveX (dotAdjust);
@@ -1967,7 +1974,7 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_
19671974 }
19681975 if (upVoices + downVoices > 1 ) {
19691976 std::sort (notes.begin (), notes.end (),
1970- [](Note* n1, const Note* n2) ->bool { return n1->line () > n2->line (); });
1977+ [](Note* n1, const Note* n2) ->bool { return n1->stringOrLine () > n2->stringOrLine (); });
19711978 }
19721979 layoutChords3 (ctx.conf ().style (), chords, notes, staff, ctx);
19731980 }
@@ -2019,9 +2026,17 @@ double ChordLayout::layoutChords2(std::vector<Note*>& notes, bool up, LayoutCont
20192026
20202027 for (int idx = startIdx; idx != endIdx; idx += incIdx) {
20212028 Note* note = notes[idx]; // current note
2022- int line = note->line (); // line of current note
2029+ const int line = note->stringOrLine (); // line of current note
20232030 Chord* chord = note->chord ();
2024- staff_idx_t staffIdx = chord->vStaffIdx (); // staff of current note
2031+ const staff_idx_t staffIdx = chord->vStaffIdx (); // staff of current note
2032+ const Staff* st = note->staff ();
2033+ const StaffType* tab = st->staffTypeForElement (note);
2034+ const bool isTab = note->staff () && note->staff ()->isTabStaff (note->chord ()->tick ());
2035+
2036+ if (isTab) {
2037+ // Need to lay out TAB note to know width
2038+ TLayout::layoutNote (note, note->mutldata ());
2039+ }
20252040
20262041 // there is a conflict
20272042 // if this is same or adjacent line as previous note (and chords are on same staff!)
@@ -2069,7 +2084,8 @@ double ChordLayout::layoutChords2(std::vector<Note*>& notes, bool up, LayoutCont
20692084
20702085 // accumulate return value
20712086 if (!mirror) {
2072- maxWidth = std::max (maxWidth, note->bboxRightPos ());
2087+ const double noteWidth = isTab ? note->tabHeadWidth (tab) : note->bboxRightPos ();
2088+ maxWidth = std::max (maxWidth, noteWidth);
20732089 }
20742090
20752091 // prepare for next iteration
@@ -2274,7 +2290,7 @@ void ChordLayout::placeDots(const std::vector<Chord*>& chords, const std::vector
22742290 }
22752291 }
22762292 }
2277- if (!chord || chord->staff ()->isTabStaff (chord->tick ())) {
2293+ if (!chord || ( chord->staff ()->isTabStaff (chord->tick ()) && !chord-> staff ()-> staffType (chord-> tick ())-> stemThrough ())) {
22782294 return ;
22792295 }
22802296 std::vector<Note*> topDownNotes;
@@ -3448,7 +3464,8 @@ void ChordLayout::layoutNote2(Note* item, LayoutContext& ctx)
34483464 double correctMag = item->chord ()->notes ().size () > 1 ? item->chord ()->mag () : item->mag ();
34493465 double d = ctx.conf ().point (ctx.conf ().styleS (Sid::dotNoteDistance)) * correctMag;
34503466 double dd = ctx.conf ().point (ctx.conf ().styleS (Sid::dotDotDistance)) * correctMag;
3451- double x = item->chord ()->dotPosX () - item->pos ().x () - item->chord ()->pos ().x ();
3467+ double x = isTabStaff ? item->chord ()->dotPosX () - item->pos ().x () : item->chord ()->dotPosX () - item->pos ().x ()
3468+ - item->chord ()->pos ().x ();
34523469 // in case of dots with different size, center-align them
34533470 if (item->mag () != item->chord ()->mag () && item->chord ()->notes ().size () > 1 ) {
34543471 double relativeMag = item->mag () / item->chord ()->mag ();
0 commit comments