LCOV - code coverage report
Current view: top level - src/engraving/dom - segment.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 47.5 % 1581 751
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include "segment.h"
      24              : 
      25              : #include <climits>
      26              : 
      27              : #include "translation.h"
      28              : 
      29              : #include "../editing/editspanner.h"
      30              : #include "../editing/navigation.h"
      31              : #include "types/typesconv.h"
      32              : #include "rendering/score/tlayout.h"
      33              : 
      34              : #include "accidental.h"
      35              : #include "barline.h"
      36              : #include "beam.h"
      37              : #include "chord.h"
      38              : #include "chordrest.h"
      39              : #include "clef.h"
      40              : #include "engravingitem.h"
      41              : #include "hammeronpulloff.h"
      42              : #include "harppedaldiagram.h"
      43              : #include "hook.h"
      44              : #include "instrchange.h"
      45              : #include "keysig.h"
      46              : #include "measure.h"
      47              : #include "mscore.h"
      48              : #include "note.h"
      49              : #include "ornament.h"
      50              : #include "part.h"
      51              : #include "rest.h"
      52              : #include "score.h"
      53              : #include "staff.h"
      54              : #include "staffstate.h"
      55              : #include "system.h"
      56              : #include "systemlockindicator.h"
      57              : #include "timesig.h"
      58              : #include "tuplet.h"
      59              : #include "utils.h"
      60              : 
      61              : #ifndef ENGRAVING_NO_ACCESSIBILITY
      62              : #include "accessibility/accessibleitem.h"
      63              : #endif
      64              : 
      65              : #include "log.h"
      66              : 
      67              : using namespace mu;
      68              : using namespace mu::engraving;
      69              : 
      70              : namespace mu::engraving {
      71              : //---------------------------------------------------------
      72              : //   subTypeName
      73              : //---------------------------------------------------------
      74              : 
      75            0 : const char* Segment::subTypeName() const
      76              : {
      77            0 :     return subTypeName(m_segmentType);
      78              : }
      79              : 
      80            0 : const char* Segment::subTypeName(SegmentType t)
      81              : {
      82            0 :     switch (t) {
      83            0 :     case SegmentType::Invalid:               return "Invalid";
      84            0 :     case SegmentType::BeginBarLine:          return "BeginBarLine";
      85            0 :     case SegmentType::HeaderClef:            return "HeaderClef";
      86            0 :     case SegmentType::Clef:                  return "Clef";
      87            0 :     case SegmentType::KeySig:                return "Key Signature";
      88            0 :     case SegmentType::Ambitus:               return "Ambitus";
      89            0 :     case SegmentType::TimeSig:               return "Time Signature";
      90            0 :     case SegmentType::StartRepeatBarLine:    return "Begin Repeat";
      91            0 :     case SegmentType::ClefStartRepeatAnnounce:    return "Clef Repeat Start Courtesy";
      92            0 :     case SegmentType::KeySigStartRepeatAnnounce:  return "Key Sig Repeat Start Courtesy";
      93            0 :     case SegmentType::TimeSigStartRepeatAnnounce: return "Time Sig Repeat Start Courtesy";
      94            0 :     case SegmentType::BarLine:               return "BarLine";
      95            0 :     case SegmentType::Breath:                return "Breath";
      96            0 :     case SegmentType::ChordRest:             return "ChordRest";
      97            0 :     case SegmentType::ClefRepeatAnnounce:    return "Clef Repeat Courtesy";
      98            0 :     case SegmentType::KeySigRepeatAnnounce:  return "Key Sig Repeat Courtesy";
      99            0 :     case SegmentType::TimeSigRepeatAnnounce: return "Time Sig Repeat Courtesy";
     100            0 :     case SegmentType::EndBarLine:            return "EndBarLine";
     101            0 :     case SegmentType::KeySigAnnounce:        return "Key Sig Courtesy";
     102            0 :     case SegmentType::TimeSigAnnounce:       return "Time Sig Courtesy";
     103            0 :     case SegmentType::TimeTick:              return "Time tick";
     104            0 :     default:
     105            0 :         return "??";
     106              :     }
     107              : }
     108              : 
     109              : //---------------------------------------------------------
     110              : //   setElement
     111              : //---------------------------------------------------------
     112              : 
     113            0 : void Segment::setElement(track_idx_t track, EngravingItem* el)
     114              : {
     115            0 :     if (el) {
     116            0 :         el->setOwnershipParent(this);
     117            0 :         m_elist[track] = el;
     118            0 :         setEmpty(false);
     119              :     } else {
     120            0 :         m_elist[track] = 0;
     121            0 :         checkEmpty();
     122              :     }
     123            0 : }
     124              : 
     125              : //---------------------------------------------------------
     126              : //   remove
     127              : //---------------------------------------------------------
     128              : 
     129            0 : void Segment::removeElement(track_idx_t track)
     130              : {
     131            0 :     EngravingItem* el = element(track);
     132            0 :     if (el && el->isChordRest()) {
     133            0 :         ChordRest* cr = (ChordRest*)el;
     134            0 :         Beam* beam = cr->beam();
     135            0 :         if (beam) {
     136            0 :             beam->remove(cr);
     137              :         }
     138            0 :         Tuplet* tuplet = cr->tuplet();
     139            0 :         if (tuplet) {
     140            0 :             tuplet->remove(cr);
     141              :         }
     142              :     }
     143            0 : }
     144              : 
     145              : //---------------------------------------------------------
     146              : //   Segment
     147              : //---------------------------------------------------------
     148              : 
     149            0 : Segment::Segment(DummyParentOr<Measure> m)
     150            0 :     : EngravingItem(ElementType::SEGMENT, m, ElementFlag::EMPTY | ElementFlag::ENABLED | ElementFlag::NOT_SELECTABLE)
     151              : {
     152            0 :     init();
     153            0 : }
     154              : 
     155        69023 : Segment::Segment(DummyParentOr<Measure> m, SegmentType st, const Fraction& t)
     156        69023 :     : EngravingItem(ElementType::SEGMENT, m, ElementFlag::EMPTY | ElementFlag::ENABLED | ElementFlag::NOT_SELECTABLE)
     157              : {
     158              : //      assert(t >= Fraction(0,1));
     159              : //      assert(t <= m->ticks());
     160        69023 :     m_segmentType = st;
     161        69023 :     m_tick = t;
     162        69023 :     init();
     163        69023 : }
     164              : 
     165              : //---------------------------------------------------------
     166              : //   Segment
     167              : //---------------------------------------------------------
     168              : 
     169            0 : Segment::Segment(const Segment& s)
     170            0 :     : EngravingItem(s)
     171              : {
     172            0 :     m_segmentType        = s.m_segmentType;
     173            0 :     m_tick               = s.m_tick;
     174            0 :     m_extraLeadingSpace  = s.m_extraLeadingSpace;
     175              : 
     176            0 :     for (EngravingItem* e : s.m_annotations) {
     177            0 :         add(e->clone());
     178              :     }
     179              : 
     180            0 :     m_elist.reserve(s.m_elist.size());
     181            0 :     for (EngravingItem* e : s.m_elist) {
     182            0 :         EngravingItem* ne = 0;
     183            0 :         if (e) {
     184            0 :             ne = e->clone();
     185            0 :             ne->setOwnershipParent(this);
     186              :         }
     187            0 :         m_elist.push_back(ne);
     188              :     }
     189            0 :     m_shapes  = s.m_shapes;
     190            0 : }
     191              : 
     192        81100 : void Segment::setOwnershipParent(DummyParentOr<Measure> parent)
     193              : {
     194        81100 :     EngravingItem::setOwnershipParent(parent);
     195        81100 : }
     196              : 
     197              : //---------------------------------------------------------
     198              : //   setSegmentType
     199              : //---------------------------------------------------------
     200              : 
     201            0 : void Segment::setSegmentType(SegmentType t)
     202              : {
     203            0 :     assert(m_segmentType != SegmentType::Clef || t != SegmentType::ChordRest);
     204            0 :     m_segmentType = t;
     205            0 : }
     206              : 
     207              : //---------------------------------------------------------
     208              : //   setScore
     209              : //---------------------------------------------------------
     210              : 
     211            0 : void Segment::setScore(Score* score)
     212              : {
     213            0 :     EngravingItem::setScore(score);
     214            0 :     for (EngravingItem* e : m_elist) {
     215            0 :         if (e) {
     216            0 :             e->setScore(score);
     217              :         }
     218              :     }
     219            0 :     for (EngravingItem* e : m_annotations) {
     220            0 :         e->setScore(score);
     221              :     }
     222            0 : }
     223              : 
     224       125636 : Segment::~Segment()
     225              : {
     226       425346 :     for (EngravingItem* e : m_elist) {
     227       362528 :         if (!e) {
     228       276143 :             continue;
     229              :         }
     230              : 
     231        86385 :         Staff* staff = e->staff();
     232              : 
     233        86385 :         if (e->isTimeSig() && staff) {
     234         3211 :             staff->removeTimeSig(toTimeSig(e));
     235              :         }
     236              : 
     237        86385 :         delete e;
     238              :     }
     239              : 
     240        62818 :     muse::DeleteAll(m_annotations);
     241       125636 : }
     242              : 
     243              : #ifndef ENGRAVING_NO_ACCESSIBILITY
     244            0 : AccessibleItemPtr Segment::createAccessible()
     245              : {
     246            0 :     return std::make_shared<AccessibleItem>(this, AccessibleItem::Group);
     247              : }
     248              : 
     249              : #endif
     250              : 
     251              : //---------------------------------------------------------
     252              : //   init
     253              : //---------------------------------------------------------
     254              : 
     255        69023 : void Segment::init()
     256              : {
     257        69023 :     size_t staves = score()->nstaves();
     258        69023 :     size_t tracks = staves * VOICES;
     259        69023 :     m_elist.assign(tracks, 0);
     260        69023 :     m_preAppendedItems.assign(tracks, 0);
     261        69023 :     m_shapes.assign(staves, Shape());
     262        69023 : }
     263              : 
     264              : //---------------------------------------------------------
     265              : //   tick
     266              : //---------------------------------------------------------
     267              : 
     268      9284061 : Fraction Segment::tick() const
     269              : {
     270      9284061 :     return m_tick + measure()->tick();
     271              : }
     272              : 
     273              : //---------------------------------------------------------
     274              : //   next1
     275              : ///   return next \a Segment, don’t stop searching at end
     276              : ///   of \a Measure
     277              : //---------------------------------------------------------
     278              : 
     279       374218 : Segment* Segment::next1() const
     280              : {
     281       374218 :     if (next()) {
     282       248421 :         return next();
     283              :     }
     284       125797 :     Measure* m = measure()->nextMeasure();
     285       125797 :     return m ? m->first() : 0;
     286              : }
     287              : 
     288              : //---------------------------------------------------------
     289              : //   next1enabled
     290              : //---------------------------------------------------------
     291              : 
     292         3920 : Segment* Segment::next1enabled() const
     293              : {
     294         3920 :     Segment* s = next1();
     295         3937 :     while (s && !s->enabled()) {
     296           17 :         s = s->next1();
     297              :     }
     298         3920 :     return s;
     299              : }
     300              : 
     301              : //---------------------------------------------------------
     302              : //   next1MM
     303              : //---------------------------------------------------------
     304              : 
     305        63907 : Segment* Segment::next1MM() const
     306              : {
     307        63907 :     if (next()) {
     308        54440 :         return next();
     309              :     }
     310         9467 :     Measure* m = measure()->nextMeasureMM();
     311         9467 :     return m ? m->first() : 0;
     312              : }
     313              : 
     314       236650 : Segment* Segment::next1(SegmentType types) const
     315              : {
     316       313589 :     for (Segment* s = next1(); s; s = s->next1()) {
     317       303938 :         if (s->segmentType() & types) {
     318       226999 :             return s;
     319              :         }
     320              :     }
     321         9651 :     return 0;
     322              : }
     323              : 
     324            0 : Segment* Segment::next1WithElemsOnStaff(staff_idx_t staffIdx, SegmentType segType) const
     325              : {
     326            0 :     Segment* next = next1(segType);
     327              : 
     328            0 :     track_idx_t startTrack = staffIdx * VOICES;
     329            0 :     track_idx_t endTrack = startTrack + VOICES - 1;
     330            0 :     while (next && !next->hasElements(startTrack, endTrack)) {
     331            0 :         next = next->next1(segType);
     332              :     }
     333              : 
     334            0 :     return next;
     335              : }
     336              : 
     337            0 : Segment* Segment::next1WithElemsOnTrack(track_idx_t trackIdx, SegmentType segType) const
     338              : {
     339            0 :     Segment* next = next1(segType);
     340              : 
     341            0 :     while (next && !next->hasElements(trackIdx, trackIdx)) {
     342            0 :         next = next->next1(segType);
     343              :     }
     344              : 
     345            0 :     return next;
     346              : }
     347              : 
     348         1074 : Segment* Segment::next1MM(SegmentType types) const
     349              : {
     350         1211 :     for (Segment* s = next1MM(); s; s = s->next1MM()) {
     351         1177 :         if (s->segmentType() & types) {
     352         1040 :             return s;
     353              :         }
     354              :     }
     355           34 :     return 0;
     356              : }
     357              : 
     358           32 : Segment* Segment::next1MMenabled() const
     359              : {
     360           32 :     Segment* s = next1MM();
     361           32 :     while (s && !s->enabled()) {
     362            0 :         s = s->next1MM();
     363              :     }
     364           32 :     return s;
     365              : }
     366              : 
     367              : //---------------------------------------------------------
     368              : //   next
     369              : //    got to next segment which has subtype in types
     370              : //---------------------------------------------------------
     371              : 
     372      1674369 : Segment* Segment::next(SegmentType types) const
     373              : {
     374      2180030 :     for (Segment* s = next(); s; s = s->next()) {
     375      1472214 :         if (s->segmentType() & types) {
     376       966553 :             return s;
     377              :         }
     378              :     }
     379       707816 :     return 0;
     380              : }
     381              : 
     382              : //---------------------------------------------------------
     383              : //   nextInStaff
     384              : ///   Returns next \c Segment in the staff with given index
     385              : //---------------------------------------------------------
     386              : 
     387            0 : Segment* Segment::nextInStaff(staff_idx_t staffIdx, SegmentType type) const
     388              : {
     389            0 :     Segment* s = next(type);
     390            0 :     const track_idx_t minTrack = staffIdx * VOICES;
     391            0 :     const track_idx_t maxTrack = (staffIdx + 1) * VOICES - 1;
     392            0 :     while (s && !s->hasElements(minTrack, maxTrack)) {
     393            0 :         s = s->next(type);
     394              :     }
     395            0 :     return s;
     396              : }
     397              : 
     398              : //---------------------------------------------------------
     399              : //   prev
     400              : //    got to previous segment which has subtype in types
     401              : //---------------------------------------------------------
     402              : 
     403       177418 : Segment* Segment::prev(SegmentType types) const
     404              : {
     405       224284 :     for (Segment* s = prev(); s; s = s->prev()) {
     406       138536 :         if (s->segmentType() & types) {
     407        91670 :             return s;
     408              :         }
     409              :     }
     410        85748 :     return 0;
     411              : }
     412              : 
     413         2808 : Segment* Segment::prevWithElementsOnTrack(track_idx_t trackIdx, SegmentType segType) const
     414              : {
     415         2808 :     Segment* prevSeg = prev(segType);
     416              : 
     417         3032 :     while (prevSeg && !prevSeg->element(trackIdx)) {
     418          224 :         prevSeg = prevSeg->prev(segType);
     419              :     }
     420              : 
     421         2808 :     return prevSeg;
     422              : }
     423              : 
     424              : //---------------------------------------------------------
     425              : //   prev1
     426              : ///   return previous \a Segment, don’t stop searching at
     427              : ///   \a Measure begin
     428              : //---------------------------------------------------------
     429              : 
     430        57399 : Segment* Segment::prev1() const
     431              : {
     432        57399 :     if (prev()) {
     433        43107 :         return prev();
     434              :     }
     435        14292 :     Measure* m = measure()->prevMeasure();
     436        14292 :     return m ? m->last() : 0;
     437              : }
     438              : 
     439            0 : Segment* Segment::prev1WithElemsOnStaff(staff_idx_t staffIdx, SegmentType segType) const
     440              : {
     441            0 :     Segment* prev = prev1(segType);
     442              : 
     443            0 :     track_idx_t startTrack = staffIdx * VOICES;
     444            0 :     track_idx_t endTrack = startTrack + VOICES - 1;
     445            0 :     while (prev && !prev->hasElements(startTrack, endTrack)) {
     446            0 :         prev = prev->prev1(segType);
     447              :     }
     448              : 
     449            0 :     return prev;
     450              : }
     451              : 
     452            0 : Segment* Segment::prev1WithElemsOnTrack(track_idx_t trackIdx, SegmentType segType) const
     453              : {
     454            0 :     Segment* prev = prev1(segType);
     455              : 
     456            0 :     while (prev && !prev->hasElements(trackIdx, trackIdx)) {
     457            0 :         prev = prev->prev1(segType);
     458              :     }
     459              : 
     460            0 :     return prev;
     461              : }
     462              : 
     463          258 : Segment* Segment::prev1enabled() const
     464              : {
     465          258 :     Segment* s = prev1();
     466          258 :     while (s && !s->enabled()) {
     467            0 :         s = s->prev1();
     468              :     }
     469          258 :     return s;
     470              : }
     471              : 
     472         5775 : Segment* Segment::prev1MM() const
     473              : {
     474         5775 :     if (prev()) {
     475         2268 :         return prev();
     476              :     }
     477         3507 :     Measure* m = measure()->prevMeasureMM();
     478         3507 :     return m ? m->last() : 0;
     479              : }
     480              : 
     481         3263 : Segment* Segment::prev1MMenabled() const
     482              : {
     483         3263 :     Segment* s = prev1MM();
     484         3286 :     while (s && !s->enabled()) {
     485           23 :         s = s->prev1MM();
     486              :     }
     487         3263 :     return s;
     488              : }
     489              : 
     490         3505 : Segment* Segment::prev1(SegmentType types) const
     491              : {
     492         5135 :     for (Segment* s = prev1(); s; s = s->prev1()) {
     493         4965 :         if (s->segmentType() & types) {
     494         3335 :             return s;
     495              :         }
     496              :     }
     497          170 :     return 0;
     498              : }
     499              : 
     500          882 : Segment* Segment::prev1MM(SegmentType types) const
     501              : {
     502         1527 :     for (Segment* s = prev1MM(); s; s = s->prev1MM()) {
     503         1324 :         if (s->segmentType() & types) {
     504          679 :             return s;
     505              :         }
     506              :     }
     507          203 :     return 0;
     508              : }
     509              : 
     510       220229 : Segment* Segment::nextActive() const
     511              : {
     512       220229 :     Segment* ns = next();
     513       222031 :     while (ns && !ns->isActive()) {
     514         1802 :         ns = ns->next();
     515              :     }
     516       220229 :     return ns;
     517              : }
     518              : 
     519            0 : Segment* Segment::nextEnabled() const
     520              : {
     521            0 :     Segment* ns = next();
     522            0 :     while (ns && !ns->enabled()) {
     523            0 :         ns = ns->next();
     524              :     }
     525            0 :     return ns;
     526              : }
     527              : 
     528        44699 : Segment* Segment::prevActive() const
     529              : {
     530        44699 :     Segment* ps = prev();
     531        45630 :     while (ps && !ps->isActive()) {
     532          931 :         ps = ps->prev();
     533              :     }
     534        44699 :     return ps;
     535              : }
     536              : 
     537         1010 : Segment* Segment::prevEnabled() const
     538              : {
     539         1010 :     Segment* ps = prev();
     540         1010 :     while (ps && !ps->enabled()) {
     541            0 :         ps = ps->prev();
     542              :     }
     543         1010 :     return ps;
     544              : }
     545              : 
     546              : //---------------------------------------------------------
     547              : //   nextCR
     548              : //    get next ChordRest Segment
     549              : //---------------------------------------------------------
     550              : 
     551         1767 : Segment* Segment::nextCR(track_idx_t track, bool sameStaff) const
     552              : {
     553         1767 :     track_idx_t strack = track;
     554              :     track_idx_t etrack;
     555         1767 :     if (sameStaff) {
     556          406 :         strack &= ~(VOICES - 1);
     557          406 :         etrack = strack + VOICES;
     558              :     } else {
     559         1361 :         etrack = strack + 1;
     560              :     }
     561         5050 :     for (Segment* seg = next1(); seg; seg = seg->next1()) {
     562         4802 :         if (seg->isChordRestType()) {
     563         3346 :             if (track == muse::nidx) {
     564          128 :                 return seg;
     565              :             }
     566         5500 :             for (track_idx_t t = strack; t < etrack; ++t) {
     567         3673 :                 if (seg->element(t)) {
     568         1391 :                     return seg;
     569              :                 }
     570              :             }
     571              :         }
     572              :     }
     573          248 :     return 0;
     574              : }
     575              : 
     576              : //---------------------------------------------------------
     577              : //   nextChordRest
     578              : //    get the next ChordRest, start at this segment
     579              : //---------------------------------------------------------
     580              : 
     581         3559 : ChordRest* Segment::nextChordRest(track_idx_t track, bool backwards, bool stopAtMeasureBoundary) const
     582              : {
     583         3559 :     const Segment* seg = this;
     584        10289 :     while (seg) {
     585         9839 :         EngravingItem* el = seg->element(track);
     586         9839 :         if (el && el->isChordRest()) {
     587         3109 :             return toChordRest(el);
     588              :         }
     589              : 
     590         6730 :         if (backwards) {
     591          267 :             seg = stopAtMeasureBoundary ? seg->prev() : seg->prev1();
     592          267 :             continue;
     593              :         }
     594              : 
     595         6463 :         seg = stopAtMeasureBoundary ? seg->next() : seg->next1();
     596              :     }
     597          450 :     return nullptr;
     598              : }
     599              : 
     600      9487675 : EngravingItem* Segment::element(track_idx_t track) const
     601              : {
     602      9487675 :     if (track >= m_elist.size()) {
     603        11647 :         return nullptr;
     604              :     }
     605              : 
     606      9476028 :     return m_elist[track];
     607              : }
     608              : 
     609       685710 : System* Segment::system() const
     610              : {
     611       685710 :     Measure* m = measure();
     612       685710 :     return m ? m->system() : nullptr;
     613              : }
     614              : 
     615              : //---------------------------------------------------------
     616              : //   insertStaff
     617              : //---------------------------------------------------------
     618              : 
     619         2305 : void Segment::insertStaff(staff_idx_t staff)
     620              : {
     621         2305 :     track_idx_t track = staff * VOICES;
     622        11525 :     for (voice_idx_t voice = 0; voice < VOICES; ++voice) {
     623         9220 :         m_elist.insert(m_elist.begin() + track, 0);
     624         9220 :         m_preAppendedItems.insert(m_preAppendedItems.begin() + track, 0);
     625              :     }
     626         2305 :     m_shapes.insert(m_shapes.begin() + staff, Shape());
     627              : 
     628         2457 :     for (EngravingItem* e : m_annotations) {
     629          152 :         if (moveDownWhenAddingStaves(e, staff)) {
     630            8 :             e->setTrack(e->track() + VOICES);
     631              :         }
     632              :     }
     633         2305 :     fixStaffIdx();
     634         2305 : }
     635              : 
     636              : //---------------------------------------------------------
     637              : //   removeStaff
     638              : //---------------------------------------------------------
     639              : 
     640         1016 : void Segment::removeStaff(staff_idx_t staff)
     641              : {
     642         1016 :     track_idx_t track = staff * VOICES;
     643         1016 :     m_elist.erase(m_elist.begin() + track, m_elist.begin() + track + VOICES);
     644         1016 :     m_preAppendedItems.erase(m_preAppendedItems.begin() + track, m_preAppendedItems.begin() + track + VOICES);
     645         1016 :     m_shapes.erase(m_shapes.begin() + staff);
     646              : 
     647         1021 :     for (EngravingItem* e : m_annotations) {
     648            5 :         staff_idx_t staffIdx = e->staffIdx();
     649            5 :         if (staffIdx > staff) {
     650            0 :             e->setTrack(e->track() - VOICES);
     651              :         }
     652              :     }
     653              : 
     654         1016 :     fixStaffIdx();
     655         1016 : }
     656              : 
     657              : //---------------------------------------------------------
     658              : //   checkElement
     659              : //---------------------------------------------------------
     660              : 
     661       100829 : void Segment::checkElement(EngravingItem* el, track_idx_t track)
     662              : {
     663              :     // prevent segmentation fault on out of bounds index
     664       100829 :     IF_ASSERT_FAILED(track < m_elist.size()) {
     665            0 :         return;
     666              :     }
     667              :     // generated elements can be overwritten
     668       100829 :     if (m_elist[track] && !m_elist[track]->generated()) {
     669         2088 :         LOGD("add(%s): there is already a %s at track %zu tick %d",
     670              :              el->typeName(),
     671          522 :              m_elist[track]->typeName(),
     672              :              track,
     673         1044 :              tick().ticks()
     674              :              );
     675              : //            abort();
     676              :     }
     677              : }
     678              : 
     679              : //---------------------------------------------------------
     680              : //   add
     681              : //---------------------------------------------------------
     682              : 
     683       105437 : void Segment::add(EngravingItem* el)
     684              : {
     685              : //      LOGD("%p segment %s add(%d, %d, %s)", this, subTypeName(), tick(), el->track(), el->typeName());
     686              : 
     687       105437 :     if (el->ownershipParent() != this) {
     688        25102 :         el->setOwnershipParent(this);
     689              :     }
     690              : 
     691       105437 :     track_idx_t track = el->track();
     692       105437 :     assert(track != muse::nidx);
     693       105437 :     assert(track < score()->ntracks());
     694       105437 :     assert(el->score() == score());
     695       105437 :     assert(score()->nstaves() * VOICES == m_elist.size());
     696              : 
     697       105437 :     switch (el->type()) {
     698          150 :     case ElementType::MEASURE_REPEAT:
     699          150 :         m_elist[track] = el;
     700          150 :         setEmpty(false);
     701          150 :         break;
     702              : 
     703              :     //fallthrough
     704         4141 :     case ElementType::HARMONY:
     705              :     case ElementType::FRET_DIAGRAM:
     706              :     case ElementType::TEMPO_TEXT:
     707              :     case ElementType::DYNAMIC:
     708              :     case ElementType::EXPRESSION:
     709              :     case ElementType::SYMBOL:
     710              :     case ElementType::STAFF_TEXT:
     711              :     case ElementType::STAVE_SHARING_LABEL:
     712              :     case ElementType::SYSTEM_TEXT:
     713              :     case ElementType::TRIPLET_FEEL:
     714              :     case ElementType::PLAYTECH_ANNOTATION:
     715              :     case ElementType::CAPO:
     716              :     case ElementType::REHEARSAL_MARK:
     717              :     case ElementType::MARKER:
     718              :     case ElementType::IMAGE:
     719              :     case ElementType::TEXT:
     720              :     case ElementType::TREMOLOBAR:
     721              :     case ElementType::TAB_DURATION_SYMBOL:
     722              :     case ElementType::FIGURED_BASS:
     723              :     case ElementType::FERMATA:
     724              :     case ElementType::STICKING:
     725         4141 :         m_annotations.push_back(el);
     726         4141 :         break;
     727              : 
     728           19 :     case ElementType::STRING_TUNINGS: {
     729           19 :         m_annotations.push_back(el);
     730              :         // Shared parts display copies of their origin parts' string tunings. Tunings should not be registered in them
     731           19 :         if (!el->part()->isSharedPart()) {
     732           19 :             el->part()->addStringTunings(toStringTunings(el));
     733              :         }
     734           19 :         break;
     735              :     }
     736              : 
     737            6 :     case ElementType::PLAY_COUNT_TEXT:
     738            6 :         assert(isType(SegmentType::BarLineTypes));
     739            6 :         if (!findAnnotation(ElementType::PLAY_COUNT_TEXT, el->track(), el->track())) {
     740            6 :             m_annotations.push_back(el);
     741              :         }
     742            6 :         break;
     743              : 
     744            0 :     case ElementType::STAFF_STATE:
     745            0 :         if (toStaffState(el)->staffStateType() == StaffStateType::INSTRUMENT) {
     746            0 :             StaffState* ss = toStaffState(el);
     747            0 :             Part* part = el->part();
     748            0 :             part->setInstrument(ss->instrument(), tick());
     749              :         }
     750            0 :         m_annotations.push_back(el);
     751            0 :         break;
     752              : 
     753           61 :     case ElementType::INSTRUMENT_CHANGE: {
     754           61 :         InstrumentChange* is = toInstrumentChange(el);
     755           61 :         Part* part = is->part();
     756           61 :         part->setInstrument(is->instrument(), tick());
     757           61 :         m_annotations.push_back(el);
     758           61 :         break;
     759              :     }
     760              : 
     761           18 :     case ElementType::HARP_DIAGRAM:
     762              :         // Shared parts display copies of their origin parts' diagrams; the origin parts own them
     763           18 :         if (el->part()->isSharedPart()) {
     764            0 :             m_annotations.push_back(el);
     765            0 :             break;
     766              :         }
     767              :         // already a diagram in this segment
     768           18 :         if (el->part()->harpDiagrams().count(toHarpPedalDiagram(el)->segment()->tick().ticks()) > 0) {
     769            0 :             break;
     770              :         }
     771           18 :         el->part()->addHarpDiagram(toHarpPedalDiagram(el));
     772           18 :         m_annotations.push_back(el);
     773           18 :         break;
     774              : 
     775         6665 :     case ElementType::CLEF:
     776         6665 :         assert(m_segmentType & SegmentType::ClefTypes);
     777         6665 :         checkElement(el, track);
     778         6665 :         m_elist[track] = el;
     779         6665 :         if (!el->generated()) {
     780         1631 :             el->staff()->setClef(toClef(el));
     781              :         }
     782         6665 :         setEmpty(false);
     783         6665 :         break;
     784              : 
     785         3906 :     case ElementType::TIMESIG:
     786         3906 :         assert(segmentType() & SegmentType::TimeSigTypes);
     787         3906 :         checkElement(el, track);
     788         3906 :         m_elist[track] = el;
     789         3906 :         el->staff()->addTimeSig(toTimeSig(el));
     790         3906 :         setEmpty(false);
     791         3906 :         if (segmentType() & SegmentType::CourtesyTimeSigTypes) {
     792          241 :             toTimeSig(el)->setIsCourtesy(true);
     793              :         }
     794         3906 :         break;
     795              : 
     796         6863 :     case ElementType::KEYSIG:
     797         6863 :         assert(m_segmentType & SegmentType::KeySigTypes);
     798         6863 :         checkElement(el, track);
     799         6863 :         m_elist[track] = el;
     800         6863 :         if (m_segmentType & SegmentType::CourtesyKeySigTypes) {
     801          330 :             toKeySig(el)->setIsCourtesy(true);
     802              :         }
     803         6863 :         if (!el->generated() && !toKeySig(el)->isCourtesy()) {
     804         1989 :             el->staff()->setKey(tick(), toKeySig(el)->keySigEvent());
     805              :         }
     806         6863 :         setEmpty(false);
     807         6863 :         break;
     808              : 
     809        55187 :     case ElementType::CHORD:
     810              :     case ElementType::REST:
     811              :     case ElementType::MMREST:
     812        55187 :         assert(m_segmentType == SegmentType::ChordRest);
     813              :         {
     814        55187 :             if (track % VOICES) {
     815              :                 bool v;
     816         3218 :                 if (el->isChord()) {
     817         2207 :                     v = false;
     818              :                     // consider chord visible if any note is visible
     819         2207 :                     Chord* c = toChord(el);
     820         2207 :                     for (Note* n : c->notes()) {
     821         1614 :                         if (n->visible()) {
     822         1614 :                             v = true;
     823         1614 :                             break;
     824              :                         }
     825              :                     }
     826              :                 } else {
     827         1011 :                     v = el->visible();
     828              :                 }
     829              : 
     830         3218 :                 if (v && measure()->score()->ntracks() > track) {
     831         2617 :                     measure()->setHasVoices(track / VOICES, true);
     832              :                 }
     833              :             }
     834              :         }
     835              :     // fall through
     836              : 
     837              :     case ElementType::BAR_LINE:
     838              :     case ElementType::BREATH:
     839        83393 :         if (track < score()->nstaves() * VOICES) {
     840        83393 :             checkElement(el, track);
     841        83393 :             m_elist[track] = el;
     842              :         }
     843        83393 :         setEmpty(false);
     844        83393 :         break;
     845              : 
     846            2 :     case ElementType::AMBITUS:
     847            2 :         assert(m_segmentType == SegmentType::Ambitus);
     848            2 :         checkElement(el, track);
     849            2 :         m_elist[track] = el;
     850            2 :         setEmpty(false);
     851            2 :         break;
     852              : 
     853          213 :     case ElementType::TIME_TICK_ANCHOR:
     854          213 :         assert(m_segmentType == SegmentType::TimeTick);
     855          213 :         m_elist[track] = el;
     856          213 :         setEmpty(false);
     857          213 :         break;
     858              : 
     859            0 :     default:
     860            0 :         ASSERT_X(String(u"Segment::add() unknown %1").arg(String::fromAscii(el->typeName())));
     861              :         return;
     862              :     }
     863              : 
     864       105437 :     el->added();
     865       105437 : }
     866              : 
     867              : //---------------------------------------------------------
     868              : //   remove
     869              : //---------------------------------------------------------
     870              : 
     871         6382 : void Segment::remove(EngravingItem* el)
     872              : {
     873              : // LOGD("%p Segment::remove %s %p", this, el->typeName(), el);
     874              : 
     875         6382 :     track_idx_t track = el->track();
     876              : 
     877         6382 :     switch (el->type()) {
     878         5586 :     case ElementType::CHORD:
     879              :     case ElementType::REST:
     880              :     {
     881         5586 :         m_elist[track] = 0;
     882         5586 :         staff_idx_t staffIdx = el->staffIdx();
     883         5586 :         measure()->checkMultiVoices(staffIdx);
     884              :         // spanners with this cr as start or end element will need relayout
     885         5586 :         SpannerMap& smap = score()->spannerMap();
     886         5586 :         auto spanners = smap.findOverlapping(tick().ticks(), tick().ticks());
     887         5780 :         for (auto interval : spanners) {
     888          194 :             Spanner* s = interval.value;
     889          194 :             EngravingItem* start = s->startElement();
     890          194 :             EngravingItem* end = s->endElement();
     891          194 :             if (s->startElement() == el) {
     892            1 :                 start = nullptr;
     893              :             }
     894          194 :             if (s->endElement() == el) {
     895            5 :                 end = nullptr;
     896              :             }
     897          194 :             if (start != s->startElement() || end != s->endElement()) {
     898            6 :                 score()->undo(new ChangeStartEndSpanner(s, start, end));
     899              :             }
     900              :         }
     901         5586 :     }
     902         5586 :     break;
     903              : 
     904           14 :     case ElementType::MMREST:
     905              :     case ElementType::MEASURE_REPEAT:
     906              :     case ElementType::TIME_TICK_ANCHOR:
     907           14 :         m_elist[track] = 0;
     908           14 :         break;
     909              : 
     910           13 :     case ElementType::HARMONY:
     911              :     case ElementType::FRET_DIAGRAM:
     912           13 :         score()->rebuildFretBox();
     913              :     //fallthrough
     914           82 :     case ElementType::DYNAMIC:
     915              :     case ElementType::EXPRESSION:
     916              :     case ElementType::FIGURED_BASS:
     917              :     case ElementType::IMAGE:
     918              :     case ElementType::MARKER:
     919              :     case ElementType::REHEARSAL_MARK:
     920              :     case ElementType::STAFF_TEXT:
     921              :     case ElementType::STAVE_SHARING_LABEL:
     922              :     case ElementType::SYSTEM_TEXT:
     923              :     case ElementType::TRIPLET_FEEL:
     924              :     case ElementType::PLAYTECH_ANNOTATION:
     925              :     case ElementType::SYMBOL:
     926              :     case ElementType::TAB_DURATION_SYMBOL:
     927              :     case ElementType::TEMPO_TEXT:
     928              :     case ElementType::TEXT:
     929              :     case ElementType::TREMOLOBAR:
     930              :     case ElementType::FERMATA:
     931              :     case ElementType::STICKING:
     932              :     case ElementType::PLAY_COUNT_TEXT:
     933           82 :         removeAnnotation(el);
     934           82 :         break;
     935            0 :     case ElementType::CAPO:
     936            0 :         for (Staff* staff : el->part()->staves()) {
     937            0 :             staff->removeCapoParams(el->tick());
     938              :         }
     939            0 :         removeAnnotation(el);
     940            0 :         break;
     941              : 
     942            0 :     case ElementType::STRING_TUNINGS:
     943            0 :         if (!el->part()->isSharedPart()) {
     944            0 :             el->part()->removeStringTunings(toStringTunings(el));
     945              :         }
     946            0 :         removeAnnotation(el);
     947            0 :         break;
     948              : 
     949            0 :     case ElementType::STAFF_STATE:
     950            0 :         if (toStaffState(el)->staffStateType() == StaffStateType::INSTRUMENT) {
     951            0 :             el->part()->removeInstrument(toStaffState(el)->instrument(), tick());
     952              :         }
     953            0 :         removeAnnotation(el);
     954            0 :         break;
     955              : 
     956            1 :     case ElementType::INSTRUMENT_CHANGE:
     957              :         // Ensure that the entry in the Part's InstrumentList for this segment's tick is the one this InstrumentChange owns:
     958            1 :         el->part()->removeInstrument(toInstrumentChange(el)->instrument(), tick());
     959            1 :         removeAnnotation(el);
     960            1 :         break;
     961              : 
     962            1 :     case ElementType::HARP_DIAGRAM:
     963            1 :         if (!el->part()->isSharedPart()) {
     964            1 :             el->part()->removeHarpDiagram(toHarpPedalDiagram(el));
     965              :         }
     966            1 :         removeAnnotation(el);
     967            1 :         break;
     968              : 
     969          153 :     case ElementType::TIMESIG:
     970          153 :         m_elist[track] = 0;
     971          153 :         el->staff()->removeTimeSig(toTimeSig(el));
     972          153 :         break;
     973              : 
     974          126 :     case ElementType::KEYSIG:
     975          126 :         m_elist[track] = 0;
     976          126 :         if (!el->generated() && !toKeySig(el)->isCourtesy()) {
     977           71 :             el->staff()->removeKey(tick());
     978              :         }
     979          126 :         break;
     980              : 
     981           70 :     case ElementType::CLEF:
     982           70 :         el->staff()->removeClef(toClef(el));
     983              :     // updateNoteLines(this, el->track());
     984              :     // fall through
     985              : 
     986          389 :     case ElementType::BAR_LINE:
     987              :     case ElementType::AMBITUS:
     988          389 :         m_elist[track] = 0;
     989          389 :         break;
     990              : 
     991           30 :     case ElementType::BREATH:
     992           30 :         m_elist[track] = 0;
     993           30 :         break;
     994              : 
     995            0 :     default:
     996            0 :         ASSERT_X(String(u"Segment::remove() unknown %1").arg(String::fromAscii(el->typeName())));
     997              :         return;
     998              :     }
     999         6382 :     triggerLayout();
    1000         6382 :     checkEmpty();
    1001         6382 :     el->removed();
    1002         6382 : }
    1003              : 
    1004              : //---------------------------------------------------------
    1005              : //   segmentType
    1006              : //    returns segment type suitable for storage of EngravingItem
    1007              : //---------------------------------------------------------
    1008              : 
    1009           41 : SegmentType Segment::segmentType(ElementType type)
    1010              : {
    1011           41 :     switch (type) {
    1012            0 :     case ElementType::CHORD:
    1013              :     case ElementType::REST:
    1014              :     case ElementType::MMREST:
    1015              :     case ElementType::MEASURE_REPEAT:
    1016              :     case ElementType::JUMP:
    1017              :     case ElementType::MARKER:
    1018            0 :         return SegmentType::ChordRest;
    1019            0 :     case ElementType::CLEF:
    1020            0 :         return SegmentType::Clef;
    1021            0 :     case ElementType::KEYSIG:
    1022            0 :         return SegmentType::KeySig;
    1023           41 :     case ElementType::TIMESIG:
    1024           41 :         return SegmentType::TimeSig;
    1025            0 :     case ElementType::BAR_LINE:
    1026            0 :         return SegmentType::StartRepeatBarLine;
    1027            0 :     case ElementType::BREATH:
    1028            0 :         return SegmentType::Breath;
    1029            0 :     default:
    1030            0 :         LOGD("Segment:segmentType():  bad type: <%s>", TConv::toXml(type).ascii());
    1031            0 :         return SegmentType::Invalid;
    1032              :     }
    1033              : }
    1034              : 
    1035              : //---------------------------------------------------------
    1036              : //   sortStaves
    1037              : //---------------------------------------------------------
    1038              : 
    1039            0 : void Segment::sortStaves(std::vector<staff_idx_t>& dst)
    1040              : {
    1041            0 :     std::vector<EngravingItem*> dl;
    1042            0 :     dl.reserve(dst.size());
    1043              : 
    1044            0 :     for (staff_idx_t i = 0; i < dst.size(); ++i) {
    1045            0 :         track_idx_t startTrack = dst[i] * VOICES;
    1046            0 :         track_idx_t endTrack   = startTrack + VOICES;
    1047            0 :         for (track_idx_t k = startTrack; k < endTrack; ++k) {
    1048            0 :             dl.push_back(m_elist[k]);
    1049              :         }
    1050              :     }
    1051            0 :     std::swap(m_elist, dl);
    1052            0 :     std::map<staff_idx_t, staff_idx_t> map;
    1053            0 :     for (staff_idx_t k = 0; k < dst.size(); ++k) {
    1054            0 :         map.insert({ dst[k], k });
    1055              :     }
    1056            0 :     for (EngravingItem* e : m_annotations) {
    1057            0 :         if (e->isTopSystemObject()) {
    1058            0 :             continue;
    1059              :         }
    1060            0 :         e->setTrack(map[e->staffIdx()] * VOICES + e->voice());
    1061              :     }
    1062            0 :     fixStaffIdx();
    1063            0 : }
    1064              : 
    1065              : //---------------------------------------------------------
    1066              : //   fixStaffIdx
    1067              : //---------------------------------------------------------
    1068              : 
    1069         3321 : void Segment::fixStaffIdx()
    1070              : {
    1071         3321 :     int track = 0;
    1072        35077 :     for (EngravingItem* e : m_elist) {
    1073        31756 :         if (e) {
    1074         5224 :             e->setTrack(track);
    1075              :         }
    1076        31756 :         ++track;
    1077              :     }
    1078         3321 : }
    1079              : 
    1080              : //---------------------------------------------------------
    1081              : //   checkEmpty
    1082              : //---------------------------------------------------------
    1083              : 
    1084         6711 : void Segment::checkEmpty() const
    1085              : {
    1086         6711 :     if (!m_annotations.empty()) {
    1087          778 :         setEmpty(false);
    1088          778 :         return;
    1089              :     }
    1090         5933 :     setEmpty(true);
    1091        25981 :     for (const EngravingItem* e : m_elist) {
    1092        22968 :         if (e) {
    1093         2920 :             setEmpty(false);
    1094         2920 :             break;
    1095              :         }
    1096              :     }
    1097              : }
    1098              : 
    1099       325807 : double Segment::xPosInSystemCoords() const
    1100              : {
    1101       325807 :     return ldata()->pos().x() + measure()->x();
    1102              : }
    1103              : 
    1104       512283 : void Segment::setXPosInSystemCoords(double x)
    1105              : {
    1106       512283 :     mutldata()->setPosX(x - measure()->x());
    1107       512283 : }
    1108              : 
    1109            0 : bool Segment::isTupletSubdivisionOnStaff(staff_idx_t staffIdx) const
    1110              : {
    1111            0 :     Fraction timeStretch = score()->staff(staffIdx)->timeStretch(tick());
    1112            0 :     int denom = (m_tick * timeStretch).reduced().denominator();
    1113            0 :     bool denomIsPowOfTwo = (denom & (denom - 1)) == 0;
    1114              :     // A non-power-of-two denominator is possible only with tuplets
    1115            0 :     return !denomIsPowOfTwo;
    1116              : }
    1117              : 
    1118           45 : bool Segment::isInsideTupletOnStaff(staff_idx_t staffIdx) const
    1119              : {
    1120           45 :     const Segment* refCRSeg = isChordRestType() && hasElements(staffIdx) ? this : prev1WithElemsOnStaff(staffIdx, SegmentType::ChordRest);
    1121           45 :     if (!refCRSeg || refCRSeg->measure() != measure()) {
    1122            0 :         return false;
    1123              :     }
    1124              : 
    1125           45 :     track_idx_t startTrack = staff2track(staffIdx);
    1126           45 :     track_idx_t endTrack = startTrack + VOICES;
    1127          225 :     for (track_idx_t track = startTrack; track < endTrack; ++track) {
    1128          180 :         ChordRest* chordRest = toChordRest(refCRSeg->element(track));
    1129          180 :         if (chordRest && chordRest->tuplet() && tick() != chordRest->topTuplet()->tick()) {
    1130            0 :             return true;
    1131              :         }
    1132              :     }
    1133              : 
    1134           45 :     return false;
    1135              : }
    1136              : 
    1137              : //---------------------------------------------------------
    1138              : //   swapElements
    1139              : //---------------------------------------------------------
    1140              : 
    1141           35 : void Segment::swapElements(track_idx_t i1, track_idx_t i2)
    1142              : {
    1143           35 :     std::iter_swap(m_elist.begin() + i1, m_elist.begin() + i2);
    1144           35 :     if (m_elist[i1]) {
    1145            9 :         m_elist[i1]->setTrack(i1);
    1146              :     }
    1147           35 :     if (m_elist[i2]) {
    1148           35 :         m_elist[i2]->setTrack(i2);
    1149              :     }
    1150           35 :     triggerLayout();
    1151           35 : }
    1152              : 
    1153              : //---------------------------------------------------------
    1154              : //   getProperty
    1155              : //---------------------------------------------------------
    1156              : 
    1157         1343 : PropertyValue Segment::getProperty(Pid propertyId) const
    1158              : {
    1159         1343 :     switch (propertyId) {
    1160          198 :     case Pid::TICK:
    1161          198 :         return m_tick;
    1162          148 :     case Pid::LEADING_SPACE:
    1163          148 :         return extraLeadingSpace();
    1164           27 :     case Pid::END_OF_MEASURE_CHANGE:
    1165           27 :         return endOfMeasureChange();
    1166          970 :     default:
    1167          970 :         return EngravingItem::getProperty(propertyId);
    1168              :     }
    1169              : }
    1170              : 
    1171              : //---------------------------------------------------------
    1172              : //   propertyDefault
    1173              : //---------------------------------------------------------
    1174              : 
    1175         1240 : PropertyValue Segment::propertyDefault(Pid propertyId) const
    1176              : {
    1177         1240 :     switch (propertyId) {
    1178          146 :     case Pid::LEADING_SPACE:
    1179          146 :         return 0.0_sp;
    1180         1094 :     default:
    1181         1094 :         return EngravingItem::propertyDefault(propertyId);
    1182              :     }
    1183              : }
    1184              : 
    1185              : //---------------------------------------------------------
    1186              : //   setProperty
    1187              : //---------------------------------------------------------
    1188              : 
    1189          691 : bool Segment::setProperty(Pid propertyId, const PropertyValue& v)
    1190              : {
    1191          691 :     switch (propertyId) {
    1192           94 :     case Pid::TICK:
    1193           94 :         setRtick(v.value<Fraction>());
    1194           94 :         break;
    1195            0 :     case Pid::LEADING_SPACE:
    1196            0 :         setExtraLeadingSpace(v.value<Spatium>());
    1197            0 :         for (EngravingItem* e : m_elist) {
    1198            0 :             if (e) {
    1199            0 :                 e->setGenerated(false);
    1200              :             }
    1201              :         }
    1202            0 :         break;
    1203            9 :     case Pid::END_OF_MEASURE_CHANGE:
    1204            9 :         setEndOfMeasureChange(v.toBool());
    1205            9 :         break;
    1206          588 :     default:
    1207          588 :         return EngravingItem::setProperty(propertyId, v);
    1208              :     }
    1209          103 :     triggerLayout();
    1210          103 :     return true;
    1211              : }
    1212              : 
    1213              : //---------------------------------------------------------
    1214              : //   widthInStaff
    1215              : //---------------------------------------------------------
    1216              : 
    1217            0 : double Segment::widthInStaff(staff_idx_t staffIdx, SegmentType nextSegType) const
    1218              : {
    1219            0 :     const double segX = x();
    1220            0 :     double nextSegX = segX;
    1221              : 
    1222            0 :     Segment* nextSeg = nextInStaff(staffIdx, nextSegType);
    1223            0 :     if (nextSeg) {
    1224            0 :         nextSegX = nextSeg->x();
    1225              :     } else {
    1226            0 :         Segment* lastSeg = measure()->lastEnabled();
    1227            0 :         if (lastSeg->segmentType() & nextSegType) {
    1228            0 :             nextSegX = lastSeg->x() + lastSeg->width();
    1229              :         } else {
    1230            0 :             nextSegX = lastSeg->x();
    1231              :         }
    1232              :     }
    1233              : 
    1234            0 :     return nextSegX - segX;
    1235              : }
    1236              : 
    1237              : //---------------------------------------------------------
    1238              : //   ticksInStaff
    1239              : //---------------------------------------------------------
    1240              : 
    1241            0 : Fraction Segment::ticksInStaff(staff_idx_t staffIdx) const
    1242              : {
    1243            0 :     const Fraction segTick = tick();
    1244            0 :     Fraction nextSegTick = segTick;
    1245              : 
    1246            0 :     Segment* nextSeg = nextInStaff(staffIdx, SegmentType::Duration);
    1247            0 :     if (nextSeg) {
    1248            0 :         nextSegTick = nextSeg->tick();
    1249              :     } else {
    1250            0 :         Segment* lastSeg = measure()->last();
    1251            0 :         nextSegTick = lastSeg->tick() + lastSeg->ticks();
    1252              :     }
    1253              : 
    1254            0 :     return nextSegTick - segTick;
    1255              : }
    1256              : 
    1257              : //---------------------------------------------------------
    1258              : //   splitsTuplet
    1259              : //---------------------------------------------------------
    1260              : 
    1261           30 : bool Segment::splitsTuplet() const
    1262              : {
    1263          162 :     for (EngravingItem* e : m_elist) {
    1264          134 :         if (!(e && e->isChordRest())) {
    1265           97 :             continue;
    1266              :         }
    1267              :         // an outer tuplet's first element is the inner tuplet, not the chord or rest
    1268           37 :         const DurationElement* el = toChordRest(e);
    1269           43 :         for (const Tuplet* t = el->tuplet(); t; el = t, t = t->tuplet()) {
    1270            8 :             if (el != t->elements().front()) {
    1271            2 :                 return true;
    1272              :             }
    1273              :         }
    1274              :     }
    1275           28 :     return false;
    1276              : }
    1277              : 
    1278              : //---------------------------------------------------------
    1279              : //   operator<
    1280              : ///   return true if segment is before s in list
    1281              : //---------------------------------------------------------
    1282              : 
    1283           59 : bool Segment::operator<(const Segment& s) const
    1284              : {
    1285           59 :     if (tick() < s.tick()) {
    1286            0 :         return true;
    1287              :     }
    1288           59 :     if (tick() > s.tick()) {
    1289           59 :         return false;
    1290              :     }
    1291            0 :     for (Segment* ns = next1(); ns && (ns->tick() == s.tick()); ns = ns->next1()) {
    1292            0 :         if (ns == &s) {
    1293            0 :             return true;
    1294              :         }
    1295              :     }
    1296            0 :     return false;
    1297              : }
    1298              : 
    1299              : //---------------------------------------------------------
    1300              : //   operator>
    1301              : ///   return true if segment is after s in list
    1302              : //---------------------------------------------------------
    1303              : 
    1304         1022 : bool Segment::operator>(const Segment& s) const
    1305              : {
    1306         1022 :     if (tick() > s.tick()) {
    1307          471 :         return true;
    1308              :     }
    1309          551 :     if (tick() < s.tick()) {
    1310            0 :         return false;
    1311              :     }
    1312          722 :     for (Segment* ns = prev1(); ns && (ns->tick() == s.tick()); ns = ns->prev1()) {
    1313          171 :         if (ns == &s) {
    1314            0 :             return true;
    1315              :         }
    1316              :     }
    1317          551 :     return false;
    1318              : }
    1319              : 
    1320              : //---------------------------------------------------------
    1321              : //   hasElements
    1322              : ///  Returns true if the segment has at least one element.
    1323              : ///  Annotations are not considered.
    1324              : //---------------------------------------------------------
    1325              : 
    1326          844 : bool Segment::hasElements() const
    1327              : {
    1328         1008 :     for (const EngravingItem* e : m_elist) {
    1329         1000 :         if (e) {
    1330          836 :             return true;
    1331              :         }
    1332              :     }
    1333            8 :     return false;
    1334              : }
    1335              : 
    1336              : //---------------------------------------------------------
    1337              : //   hasElements
    1338              : ///  return true if an annotation of type type or and element is found in the track range
    1339              : //---------------------------------------------------------
    1340              : 
    1341        17558 : bool Segment::hasElements(track_idx_t minTrack, track_idx_t maxTrack) const
    1342              : {
    1343        17920 :     for (track_idx_t curTrack = minTrack; curTrack <= maxTrack; curTrack++) {
    1344        17885 :         if (element(curTrack)) {
    1345        17523 :             return true;
    1346              :         }
    1347              :     }
    1348           35 :     return false;
    1349              : }
    1350              : 
    1351        17314 : bool Segment::hasElements(staff_idx_t staffIdx) const
    1352              : {
    1353        17314 :     track_idx_t startTrack = staffIdx * VOICES;
    1354        17314 :     track_idx_t endTrack = startTrack + VOICES - 1;
    1355        17314 :     return hasElements(startTrack, endTrack);
    1356              : }
    1357              : 
    1358              : //---------------------------------------------------------
    1359              : //   allElementsInvisible
    1360              : ///  return true if all elements in the segment are invisible
    1361              : //---------------------------------------------------------
    1362              : 
    1363       709126 : bool Segment::allElementsInvisible() const
    1364              : {
    1365       709126 :     if (isType(SegmentType::TimeTick)) {
    1366            5 :         return true;
    1367              :     }
    1368              : 
    1369       709121 :     if (isType(SegmentType::BarLineTypes | SegmentType::ChordRest)) {
    1370       597821 :         return false;
    1371              :     }
    1372              : 
    1373       111300 :     System* sys = system();
    1374       166793 :     for (staff_idx_t staffIdx = 0; staffIdx < score()->nstaves(); ++staffIdx) {
    1375       133415 :         Staff* staff = score()->staves().at(staffIdx);
    1376       133415 :         if (!staff->visible()) {
    1377           55 :             continue;
    1378              :         }
    1379       133360 :         if (sys && staffIdx < sys->staves().size() && !sys->staves().at(staffIdx)->show()) {
    1380         1910 :             continue;
    1381              :         }
    1382       131450 :         track_idx_t endTrack = staffIdx * VOICES + VOICES;
    1383       345562 :         for (track_idx_t track = staffIdx * VOICES; track < endTrack; ++track) {
    1384       292034 :             EngravingItem* e = m_elist[track];
    1385       292034 :             if (e && e->visible() && !muse::RealIsEqual(e->width(), 0.0)) {
    1386        77922 :                 return false;
    1387              :             }
    1388              :         }
    1389              :     }
    1390              : 
    1391        33378 :     return true;
    1392              : }
    1393              : 
    1394              : //---------------------------------------------------------
    1395              : //   hasAnnotationOrElement
    1396              : ///  return true if an annotation of type type or and element is found in the track range
    1397              : //---------------------------------------------------------
    1398              : 
    1399            0 : bool Segment::hasAnnotationOrElement(ElementType type, track_idx_t minTrack, track_idx_t maxTrack) const
    1400              : {
    1401            0 :     for (const EngravingItem* e : m_annotations) {
    1402            0 :         if (e->type() == type && e->track() >= minTrack && e->track() <= maxTrack) {
    1403            0 :             return true;
    1404              :         }
    1405              :     }
    1406            0 :     return hasElements(minTrack, maxTrack);
    1407              : }
    1408              : 
    1409            0 : bool Segment::hasAnnotationOrElement(staff_idx_t staffIdx) const
    1410              : {
    1411            0 :     for (const EngravingItem* e : m_annotations) {
    1412            0 :         if (e->staffIdx() == staffIdx) {
    1413            0 :             return true;
    1414              :         }
    1415              :     }
    1416            0 :     return hasElements(staffIdx);
    1417              : }
    1418              : 
    1419              : //---------------------------------------------------------
    1420              : //   findAnnotation
    1421              : ///  Returns the first found annotation of type type
    1422              : ///  or nullptr if nothing was found.
    1423              : //---------------------------------------------------------
    1424              : 
    1425       130274 : EngravingItem* Segment::findAnnotation(ElementType type, track_idx_t minTrack, track_idx_t maxTrack) const
    1426              : {
    1427       134425 :     for (EngravingItem* e : m_annotations) {
    1428         5289 :         if (e->type() == type && e->track() >= minTrack && e->track() <= maxTrack) {
    1429         1138 :             return e;
    1430              :         }
    1431              :     }
    1432       129136 :     return nullptr;
    1433              : }
    1434              : 
    1435              : //---------------------------------------------------------
    1436              : //   findAnnotations
    1437              : ///  Returns the list of found annotations
    1438              : ///  or an empty list if nothing was found.
    1439              : //---------------------------------------------------------
    1440              : 
    1441        11824 : std::vector<EngravingItem*> Segment::findAnnotations(ElementType type, track_idx_t minTrack, track_idx_t maxTrack) const
    1442              : {
    1443        11824 :     std::vector<EngravingItem*> found;
    1444        14533 :     for (EngravingItem* e : m_annotations) {
    1445         2709 :         if (e->type() == type && e->track() >= minTrack && e->track() <= maxTrack) {
    1446          113 :             found.push_back(e);
    1447              :         }
    1448              :     }
    1449        11824 :     return found;
    1450            0 : }
    1451              : 
    1452              : //---------------------------------------------------------
    1453              : //   removeAnnotation
    1454              : //---------------------------------------------------------
    1455              : 
    1456          109 : void Segment::removeAnnotation(EngravingItem* e)
    1457              : {
    1458          158 :     for (auto i = m_annotations.begin(); i != m_annotations.end(); ++i) {
    1459          158 :         if (*i == e) {
    1460          109 :             m_annotations.erase(i);
    1461          109 :             break;
    1462              :         }
    1463              :     }
    1464          109 : }
    1465              : 
    1466              : //---------------------------------------------------------
    1467              : //   clearAnnotations
    1468              : //---------------------------------------------------------
    1469              : 
    1470            0 : void Segment::clearAnnotations()
    1471              : {
    1472            0 :     m_annotations.clear();
    1473            0 : }
    1474              : 
    1475              : //---------------------------------------------------------
    1476              : //   scanElements
    1477              : //---------------------------------------------------------
    1478              : 
    1479        12158 : void Segment::scanElements(std::function<void(EngravingItem*)> func)
    1480              : {
    1481        12158 :     bool scanAllTimeSigs = (isType(SegmentType::TimeSigTypes)
    1482        12158 :                             && style().styleV(Sid::timeSigPlacement).value<TimeSigPlacement>() != TimeSigPlacement::NORMAL);
    1483        74264 :     for (size_t track = 0; track < score()->nstaves() * VOICES; ++track) {
    1484        62106 :         size_t staffIdx = track / VOICES;
    1485        62106 :         bool thisMeasureVisible = measure()->visible(staffIdx) && score()->staff(staffIdx)->show();
    1486        62106 :         if (!scanAllTimeSigs && !thisMeasureVisible) {
    1487          342 :             Measure* nextMeasure = measure()->nextMeasure();
    1488              :             bool nextMeasureVisible = nextMeasure
    1489          142 :                                       && nextMeasure->system() == measure()->system()
    1490          130 :                                       && nextMeasure->visible(staffIdx)
    1491          484 :                                       && score()->staff(staffIdx)->show();
    1492          684 :             if (!((isEndBarLineType() && (nextMeasureVisible || measure()->isCutawayClef(staffIdx)))
    1493          342 :                   || (isClefType() && measure()->isCutawayClef(staffIdx)))) {
    1494          342 :                 track += VOICES - 1;
    1495          342 :                 continue;
    1496              :             }
    1497              :         }
    1498        61764 :         EngravingItem* e = element(track);
    1499        61764 :         if (e == 0) {
    1500        50015 :             continue;
    1501              :         }
    1502        11749 :         e->scanElements(func);
    1503              :     }
    1504        12948 :     for (EngravingItem* e : annotations()) {
    1505          790 :         if (!e->systemFlag() && (!measure() || !measure()->visible(e->staffIdx()))) {
    1506            2 :             continue;
    1507              :         }
    1508          788 :         e->scanElements(func);
    1509              :     }
    1510        12158 : }
    1511              : 
    1512              : //---------------------------------------------------------
    1513              : //   firstElement
    1514              : //   This function returns the first main element from a
    1515              : //   segment, or a barline if it spanns in the staff
    1516              : //---------------------------------------------------------
    1517              : 
    1518           38 : EngravingItem* Segment::firstElementForNavigation(staff_idx_t staff) const
    1519              : {
    1520           38 :     if (isChordRestType()) {
    1521            9 :         track_idx_t strack = staff * VOICES;
    1522            9 :         track_idx_t etrack = strack + VOICES;
    1523            9 :         for (track_idx_t v = strack; v < etrack; ++v) {
    1524            9 :             EngravingItem* el = element(v);
    1525            9 :             if (!el) {
    1526            0 :                 continue;
    1527              :             }
    1528            9 :             return el->isChord() ? toChord(el)->notes().back() : el;
    1529              :         }
    1530              :     } else {
    1531           29 :         return getElement(staff);
    1532              :     }
    1533            0 :     return 0;
    1534              : }
    1535              : 
    1536              : //---------------------------------------------------------
    1537              : //   lastElement
    1538              : //   This function returns the last main element from a
    1539              : //   segment, or a barline if it spanns in the staff
    1540              : //---------------------------------------------------------
    1541              : 
    1542            0 : EngravingItem* Segment::lastElementForNavigation(staff_idx_t staff) const
    1543              : {
    1544            0 :     if (segmentType() == SegmentType::ChordRest) {
    1545            0 :         for (int voice = static_cast<int>(staff * VOICES + (VOICES - 1)); voice / static_cast<int>(VOICES) == static_cast<int>(staff);
    1546              :              voice--) {
    1547            0 :             EngravingItem* el = element(voice);
    1548            0 :             if (!el) {            //there is no chord or rest on this voice
    1549            0 :                 continue;
    1550              :             }
    1551            0 :             if (el->isChord()) {
    1552            0 :                 return toChord(el)->notes().front();
    1553              :             } else {
    1554            0 :                 return el;
    1555              :             }
    1556              :         }
    1557              :     } else {
    1558            0 :         return getElement(staff);
    1559              :     }
    1560              : 
    1561            0 :     return 0;
    1562              : }
    1563              : 
    1564              : //---------------------------------------------------------
    1565              : //   getElement
    1566              : //   protected because it is used by the firstElement and
    1567              : //   lastElement functions when segment types that have
    1568              : //   just one element to avoid duplicated code
    1569              : //
    1570              : //   Use firstElement, or lastElement instead of this
    1571              : //---------------------------------------------------------
    1572              : 
    1573           29 : EngravingItem* Segment::getElement(staff_idx_t staff) const
    1574              : {
    1575           29 :     segmentType();
    1576           29 :     if (segmentType() == SegmentType::ChordRest) {
    1577            0 :         return firstElementForNavigation(staff);
    1578           29 :     } else if (segmentType() & (SegmentType::EndBarLine | SegmentType::BarLine | SegmentType::StartRepeatBarLine)) {
    1579            0 :         for (int i = static_cast<int>(staff); i >= 0; i--) {
    1580            0 :             if (!element(i * VOICES)) {
    1581            0 :                 continue;
    1582              :             }
    1583            0 :             BarLine* b = toBarLine(element(i * VOICES));
    1584            0 :             if (i + b->spanStaff() >= static_cast<int>(staff)) {
    1585            0 :                 return element(i * VOICES);
    1586              :             }
    1587              :         }
    1588              :     } else {
    1589           29 :         return element(staff * VOICES);
    1590              :     }
    1591            0 :     return 0;
    1592              : }
    1593              : 
    1594              : //---------------------------------------------------------
    1595              : //   nextAnnotation
    1596              : //   return next element in _annotations
    1597              : //---------------------------------------------------------
    1598              : 
    1599            0 : EngravingItem* Segment::nextAnnotation(EngravingItem* e) const
    1600              : {
    1601            0 :     if (m_annotations.empty() || e == m_annotations.back()) {
    1602            0 :         return nullptr;
    1603              :     }
    1604            0 :     auto ei = std::find(m_annotations.begin(), m_annotations.end(), e);
    1605            0 :     if (ei == m_annotations.end()) {
    1606            0 :         return nullptr;                   // element not found
    1607              :     }
    1608              :     // TODO: firstVisibleStaff() for system elements? see Spanner::nextSpanner()
    1609            0 :     auto resIt = std::find_if(ei + 1, m_annotations.end(), [e](EngravingItem* nextElem) {
    1610            0 :         return nextElem && nextElem->staffIdx() == e->staffIdx();
    1611              :     });
    1612              : 
    1613            0 :     return m_annotations.end() == resIt ? nullptr : *resIt;
    1614              : }
    1615              : 
    1616              : //---------------------------------------------------------
    1617              : //   prevAnnotation
    1618              : //   return previous element in _annotations
    1619              : //---------------------------------------------------------
    1620              : 
    1621            0 : EngravingItem* Segment::prevAnnotation(EngravingItem* e) const
    1622              : {
    1623            0 :     if (e == m_annotations.front()) {
    1624            0 :         return nullptr;
    1625              :     }
    1626            0 :     auto reverseIt = std::find(m_annotations.rbegin(), m_annotations.rend(), e);
    1627            0 :     if (reverseIt == m_annotations.rend()) {
    1628            0 :         return nullptr;                   // element not found
    1629              :     }
    1630              :     // TODO: firstVisibleStaff() for system elements? see Spanner::nextSpanner()
    1631            0 :     auto resIt = std::find_if(reverseIt + 1, m_annotations.rend(), [e](EngravingItem* prevElem) {
    1632            0 :         return prevElem && prevElem->staffIdx() == e->staffIdx();
    1633            0 :     });
    1634              : 
    1635            0 :     return m_annotations.rend() == resIt ? nullptr : *resIt;
    1636              : }
    1637              : 
    1638              : //---------------------------------------------------------
    1639              : //   firstAnnotation
    1640              : //---------------------------------------------------------
    1641              : 
    1642            0 : EngravingItem* Segment::firstAnnotation(staff_idx_t activeStaff) const
    1643              : {
    1644            0 :     for (auto i = m_annotations.begin(); i != m_annotations.end(); ++i) {
    1645              :         // TODO: firstVisibleStaff() for system elements? see Spanner::nextSpanner()
    1646            0 :         if ((*i)->staffIdx() == activeStaff) {
    1647            0 :             return *i;
    1648              :         }
    1649              :     }
    1650            0 :     return nullptr;
    1651              : }
    1652              : 
    1653              : //---------------------------------------------------------
    1654              : //   lastAnnotation
    1655              : //---------------------------------------------------------
    1656              : 
    1657            0 : EngravingItem* Segment::lastAnnotation(staff_idx_t activeStaff) const
    1658              : {
    1659            0 :     for (auto i = m_annotations.rbegin(); i != m_annotations.rend(); ++i) {
    1660              :         // TODO: firstVisibleStaff() for system elements? see Spanner::nextSpanner()
    1661            0 :         EngravingItem* e = *i;
    1662            0 :         IF_ASSERT_FAILED(e) {
    1663            0 :             continue;
    1664              :         }
    1665            0 :         if (e->staffIdx() == activeStaff) {
    1666            0 :             return e;
    1667              :         }
    1668              :     }
    1669            0 :     return nullptr;
    1670              : }
    1671              : 
    1672              : //--------------------------------------------------------
    1673              : //   firstInNextSegments
    1674              : //   Searches for the next segment that has elements on the
    1675              : //   active staff and returns its first element
    1676              : //
    1677              : //   Uses firstElement so it also returns a barline if it
    1678              : //   spans into the active staff
    1679              : //--------------------------------------------------------
    1680              : 
    1681           32 : EngravingItem* Segment::firstInNextSegments(staff_idx_t activeStaff) const
    1682              : {
    1683           32 :     EngravingItem* re = 0;
    1684           32 :     const Segment* seg = this;
    1685           64 :     while (!re) {
    1686           32 :         seg = seg->next1MMenabled();
    1687           32 :         if (!seg) {   //end of staff, or score
    1688            0 :             break;
    1689              :         }
    1690              : 
    1691           32 :         re = seg->firstElementForNavigation(activeStaff);
    1692              :     }
    1693              : 
    1694           32 :     if (re) {
    1695           32 :         return re;
    1696              :     }
    1697              : 
    1698            0 :     if (!seg) {   //end of staff
    1699            0 :         if (activeStaff + 1 >= score()->nstaves()) {   //end of score
    1700            0 :             return 0;
    1701              :         }
    1702            0 :         seg = score()->firstSegmentMM(SegmentType::All);
    1703            0 :         return seg->element((activeStaff + 1) * VOICES);
    1704              :     }
    1705            0 :     return 0;
    1706              : }
    1707              : 
    1708              : //---------------------------------------------------------
    1709              : //   firstElementOfSegment
    1710              : //   returns the first non null element
    1711              : //---------------------------------------------------------
    1712              : 
    1713          631 : EngravingItem* Segment::firstElementOfSegment(staff_idx_t activeStaff) const
    1714              : {
    1715          631 :     if (isTimeTickType()) {
    1716            0 :         return nullptr;
    1717              :     }
    1718              : 
    1719         1299 :     for (auto i: m_elist) {
    1720         1165 :         if (i && i->staffIdx() == activeStaff) {
    1721          497 :             if (i->isDurationElement()) {
    1722          497 :                 DurationElement* de = toDurationElement(i);
    1723          497 :                 Tuplet* tuplet = de->tuplet();
    1724          497 :                 if (tuplet && de == tuplet->elements().front()) {
    1725          497 :                     return tuplet;
    1726              :                 }
    1727              :             }
    1728              : 
    1729          497 :             if (i->isChord()) {
    1730          213 :                 Chord* chord = toChord(i);
    1731          213 :                 return chord->firstGraceOrNote();
    1732              :             } else {
    1733          284 :                 return i;
    1734              :             }
    1735              :         }
    1736              :     }
    1737          134 :     return nullptr;
    1738              : }
    1739              : 
    1740              : //---------------------------------------------------------
    1741              : //   nextElementOfSegment
    1742              : //   returns the next element after the given element
    1743              : //---------------------------------------------------------
    1744              : 
    1745            0 : EngravingItem* Segment::nextElementOfSegment(EngravingItem* e, staff_idx_t activeStaff) const
    1746              : {
    1747            0 :     for (size_t track = 0; track < score()->nstaves() * VOICES - 1; ++track) {
    1748            0 :         if (element(track) == 0) {
    1749            0 :             continue;
    1750              :         }
    1751            0 :         EngravingItem* el = element(track);
    1752            0 :         if (el == e) {
    1753            0 :             EngravingItem* next = element(track + 1);
    1754            0 :             while (track < score()->nstaves() * VOICES - 1
    1755            0 :                    && (!next || next->staffIdx() != activeStaff)) {
    1756            0 :                 next = element(++track);
    1757              :             }
    1758            0 :             if (!next || next->staffIdx() != activeStaff) {
    1759            0 :                 return nullptr;
    1760              :             }
    1761            0 :             if (next->isChord()) {
    1762            0 :                 return toChord(next)->notes().back();
    1763              :             } else {
    1764            0 :                 return next;
    1765              :             }
    1766              :         }
    1767            0 :         if (el->isChord()) {
    1768            0 :             std::vector<Note*> notes = toChord(el)->notes();
    1769            0 :             auto i = std::find(notes.begin(), notes.end(), e);
    1770            0 :             if (i == notes.end()) {
    1771            0 :                 continue;
    1772              :             }
    1773            0 :             if (i != notes.begin()) {
    1774            0 :                 return *(i - 1);
    1775              :             } else {
    1776            0 :                 EngravingItem* nextEl = element(++track);
    1777            0 :                 while (track < score()->nstaves() * VOICES - 1
    1778            0 :                        && (!nextEl || nextEl->staffIdx() != activeStaff)) {
    1779            0 :                     nextEl = element(++track);
    1780              :                 }
    1781            0 :                 if (!nextEl || nextEl->staffIdx() != activeStaff) {
    1782            0 :                     return nullptr;
    1783              :                 }
    1784            0 :                 if (nextEl->isChord()) {
    1785            0 :                     return toChord(nextEl)->notes().back();
    1786              :                 }
    1787            0 :                 return nextEl;
    1788              :             }
    1789            0 :         }
    1790              :     }
    1791            0 :     return nullptr;
    1792              : }
    1793              : 
    1794              : //---------------------------------------------------------
    1795              : //   prevElementOfSegment
    1796              : //   returns the previous element before the given element
    1797              : //---------------------------------------------------------
    1798              : 
    1799            0 : EngravingItem* Segment::prevElementOfSegment(EngravingItem* e, staff_idx_t activeStaff) const
    1800              : {
    1801            0 :     for (int track = static_cast<int>(score()->nstaves() * VOICES) - 1; track > 0; --track) {
    1802            0 :         if (element(track) == 0) {
    1803            0 :             continue;
    1804              :         }
    1805            0 :         EngravingItem* el = element(track);
    1806            0 :         if (el == e) {
    1807            0 :             EngravingItem* prev = element(track - 1);
    1808            0 :             while (track > 0
    1809            0 :                    && (!prev || prev->staffIdx() != activeStaff)) {
    1810            0 :                 prev = element(--track);
    1811              :             }
    1812            0 :             if (!prev) {
    1813            0 :                 return nullptr;
    1814              :             }
    1815            0 :             if (prev->staffIdx() == e->staffIdx()) {
    1816            0 :                 if (prev->isChord()) {
    1817            0 :                     return toChord(prev)->notes().front();
    1818              :                 } else {
    1819            0 :                     return prev;
    1820              :                 }
    1821              :             }
    1822            0 :             return nullptr;
    1823              :         }
    1824            0 :         if (el->isChord()) {
    1825            0 :             Chord* chord = toChord(el);
    1826            0 :             GraceNotesGroup& graceNotesBefore = chord->graceNotesBefore();
    1827            0 :             if (!graceNotesBefore.empty()) {
    1828            0 :                 ChordRest* next = Navigation::prevChordRest(chord);
    1829            0 :                 if (next) {
    1830            0 :                     if (next->isChord()) {
    1831            0 :                         return toChord(next)->notes().back();
    1832              :                     }
    1833            0 :                     return toRest(next);
    1834              :                 }
    1835              :             }
    1836              : 
    1837            0 :             std::vector<Note*> notes = chord->notes();
    1838            0 :             auto i = std::find(notes.begin(), notes.end(), e);
    1839            0 :             if (i == notes.end()) {
    1840            0 :                 continue;
    1841              :             }
    1842            0 :             if (i != --notes.end()) {
    1843            0 :                 return *(i + 1);
    1844              :             } else {
    1845            0 :                 EngravingItem* prevEl = element(--track);
    1846            0 :                 while (track > 0
    1847            0 :                        && (!prevEl || prevEl->staffIdx() != activeStaff)) {
    1848            0 :                     prevEl = element(--track);
    1849              :                 }
    1850            0 :                 if (!prevEl) {
    1851            0 :                     return nullptr;
    1852              :                 }
    1853            0 :                 if (prevEl->staffIdx() == e->staffIdx()) {
    1854            0 :                     if (prevEl->isChord()) {
    1855            0 :                         return toChord(prevEl)->notes().front();
    1856              :                     }
    1857            0 :                     return prevEl;
    1858              :                 }
    1859            0 :                 return nullptr;
    1860              :             }
    1861            0 :         }
    1862              :     }
    1863            0 :     return nullptr;
    1864              : }
    1865              : 
    1866              : //---------------------------------------------------------
    1867              : //   lastElementOfSegment
    1868              : //   returns the last element
    1869              : //---------------------------------------------------------
    1870              : 
    1871           29 : EngravingItem* Segment::lastElementOfSegment(staff_idx_t activeStaff) const
    1872              : {
    1873           29 :     if (isTimeTickType()) {
    1874            0 :         return nullptr;
    1875              :     }
    1876              : 
    1877           29 :     const std::vector<EngravingItem*>& elements = m_elist;
    1878          124 :     for (auto it = elements.rbegin(); it != elements.rend(); ++it) {
    1879          124 :         EngravingItem* item = *it;
    1880          124 :         if (item && item->staffIdx() == activeStaff) {
    1881           29 :             if (item->isChord()) {
    1882            0 :                 Chord* chord = toChord(item);
    1883            0 :                 if (!chord->graceNotesAfter().empty()) {
    1884           29 :                     return chord->graceNotesAfter().back()->notes().back();
    1885              :                 }
    1886              : 
    1887            0 :                 const std::vector<Articulation*>& articulations = chord->articulations();
    1888            0 :                 if (!articulations.empty()) {
    1889            0 :                     Articulation* lastArtic = articulations.back();
    1890            0 :                     if (lastArtic->isTapping()) {
    1891            0 :                         Tapping* tap = toTapping(lastArtic);
    1892            0 :                         if (tap->halfSlurBelow()) {
    1893            0 :                             return tap->halfSlurBelow()->frontSegment();
    1894            0 :                         } else if (tap->halfSlurAbove()) {
    1895            0 :                             return tap->halfSlurAbove()->frontSegment();
    1896              :                         }
    1897              :                     }
    1898            0 :                     return lastArtic;
    1899              :                 }
    1900            0 :                 return chord->upNote();
    1901              :             }
    1902           29 :             return item;
    1903              :         }
    1904              :     }
    1905            0 :     return nullptr;
    1906              : }
    1907              : 
    1908              : //---------------------------------------------------------
    1909              : //   firstSpanner
    1910              : //---------------------------------------------------------
    1911              : 
    1912            0 : Spanner* Segment::firstSpanner(staff_idx_t activeStaff) const
    1913              : {
    1914            0 :     std::multimap<int, Spanner*> mmap = score()->spanner();
    1915            0 :     auto range = mmap.equal_range(tick().ticks());
    1916            0 :     if (range.first != range.second) {  // range not empty
    1917            0 :         for (auto i = range.first; i != range.second; ++i) {
    1918            0 :             Spanner* s = i->second;
    1919            0 :             if (s->segmentsEmpty()) {
    1920            0 :                 continue;
    1921              :             }
    1922              : 
    1923            0 :             EngravingItem* e = s->startElement();
    1924            0 :             if (!e) {
    1925            0 :                 continue;
    1926              :             }
    1927            0 :             if (s->startSegment() == this) {
    1928            0 :                 if (e->staffIdx() == activeStaff || (e->isMeasure() && activeStaff == 0)) {
    1929            0 :                     return s;
    1930              :                 }
    1931              :             }
    1932              :         }
    1933              :     }
    1934            0 :     return nullptr;
    1935            0 : }
    1936              : 
    1937              : //---------------------------------------------------------
    1938              : //   lastSpanner
    1939              : //---------------------------------------------------------
    1940              : 
    1941            0 : Spanner* Segment::lastSpanner(staff_idx_t activeStaff) const
    1942              : {
    1943            0 :     std::multimap<int, Spanner*> mmap = score()->spanner();
    1944            0 :     auto range = mmap.equal_range(tick().ticks());
    1945            0 :     if (range.first != range.second) {  // range not empty
    1946            0 :         for (auto i = --range.second;; --i) {
    1947            0 :             Spanner* s = i->second;
    1948            0 :             if (s->segmentsEmpty()) {
    1949            0 :                 continue;
    1950              :             }
    1951              : 
    1952            0 :             EngravingItem* e = s->startElement();
    1953            0 :             if (!e) {
    1954            0 :                 continue;
    1955              :             }
    1956            0 :             if (s->startSegment() == this) {
    1957            0 :                 if (e->staffIdx() == activeStaff || (e->isMeasure() && activeStaff == 0)) {
    1958            0 :                     return s;
    1959              :                 }
    1960              :             }
    1961            0 :             if (i == range.first) {
    1962            0 :                 break;
    1963              :             }
    1964            0 :         }
    1965              :     }
    1966            0 :     return nullptr;
    1967            0 : }
    1968              : 
    1969              : //---------------------------------------------------------
    1970              : //   notChordRestType
    1971              : //---------------------------------------------------------
    1972              : 
    1973            0 : bool Segment::notChordRestType() const
    1974              : {
    1975            0 :     return segmentType() != SegmentType::ChordRest;
    1976              : }
    1977              : 
    1978              : //---------------------------------------------------------
    1979              : //   nextElement
    1980              : //---------------------------------------------------------
    1981              : 
    1982            0 : EngravingItem* Segment::nextElement(staff_idx_t activeStaff)
    1983              : {
    1984            0 :     EngravingItem* e = score()->selection().element();
    1985            0 :     if (!e && !score()->selection().elements().empty()) {
    1986            0 :         e = score()->selection().elements().front();
    1987              :     }
    1988            0 :     if (!e) {
    1989            0 :         return nullptr;
    1990              :     }
    1991            0 :     switch (e->type()) {
    1992            0 :     case ElementType::DYNAMIC:
    1993              :     case ElementType::HARMONY:
    1994              :     case ElementType::EXPRESSION:
    1995              :     case ElementType::SYMBOL:
    1996              :     case ElementType::FERMATA:
    1997              :     case ElementType::FRET_DIAGRAM:
    1998              :     case ElementType::TEMPO_TEXT:
    1999              :     case ElementType::STAFF_TEXT:
    2000              :     case ElementType::STAVE_SHARING_LABEL:
    2001              :     case ElementType::SYSTEM_TEXT:
    2002              :     case ElementType::TRIPLET_FEEL:
    2003              :     case ElementType::PLAYTECH_ANNOTATION:
    2004              :     case ElementType::CAPO:
    2005              :     case ElementType::STRING_TUNINGS:
    2006              :     case ElementType::REHEARSAL_MARK:
    2007              :     case ElementType::MARKER:
    2008              :     case ElementType::IMAGE:
    2009              :     case ElementType::TEXT:
    2010              :     case ElementType::TREMOLOBAR:
    2011              :     case ElementType::TAB_DURATION_SYMBOL:
    2012              :     case ElementType::FIGURED_BASS:
    2013              :     case ElementType::STAFF_STATE:
    2014              :     case ElementType::INSTRUMENT_CHANGE:
    2015              :     case ElementType::HARP_DIAGRAM:
    2016              :     case ElementType::STICKING:
    2017              :     case ElementType::TUPLET: {
    2018            0 :         EngravingItem* next = nullptr;
    2019            0 :         if (e->ownershipParent() == this) {
    2020            0 :             next = nextAnnotation(e);
    2021              : 
    2022            0 :             if (next && next->isFretDiagram()) {
    2023            0 :                 FretDiagram* fretDiagram = toFretDiagram(next);
    2024            0 :                 if (fretDiagram->harmony()) {
    2025            0 :                     next = fretDiagram->harmony();
    2026              :                 }
    2027              :             }
    2028              :         }
    2029            0 :         if (next) {
    2030            0 :             return next;
    2031              :         } else {
    2032            0 :             Spanner* s = firstSpanner(activeStaff);
    2033            0 :             if (s) {
    2034            0 :                 return s->spannerSegments().front();
    2035              :             }
    2036              :         }
    2037            0 :         Segment* nextSegment = this->next1MMenabled();
    2038            0 :         while (nextSegment) {
    2039            0 :             EngravingItem* nextEl = nextSegment->firstElementOfSegment(activeStaff);
    2040            0 :             if (nextEl) {
    2041            0 :                 return nextEl;
    2042              :             }
    2043              : 
    2044            0 :             if (EngravingItem* annotation = nextSegment->firstAnnotation(activeStaff)) {
    2045            0 :                 if (annotation && annotation->isFretDiagram()) {
    2046            0 :                     FretDiagram* fretDiagram = toFretDiagram(annotation);
    2047            0 :                     if (fretDiagram->harmony()) {
    2048            0 :                         annotation = fretDiagram->harmony();
    2049              :                     }
    2050              :                 }
    2051              : 
    2052            0 :                 return annotation;
    2053              :             }
    2054              : 
    2055            0 :             nextSegment = nextSegment->next1MMenabled();
    2056              :         }
    2057            0 :         break;
    2058              :     }
    2059            0 :     case ElementType::SEGMENT: {
    2060            0 :         if (!m_annotations.empty()) {
    2061            0 :             EngravingItem* next = firstAnnotation(activeStaff);
    2062            0 :             if (next) {
    2063            0 :                 if (next->isFretDiagram()) {
    2064            0 :                     if (Harmony* harmony = toFretDiagram(next)->harmony()) {
    2065            0 :                         return harmony;
    2066              :                     }
    2067              :                 }
    2068              : 
    2069            0 :                 return next;
    2070              :             }
    2071              :         }
    2072            0 :         Spanner* sp = firstSpanner(activeStaff);
    2073            0 :         if (sp) {
    2074            0 :             return sp->spannerSegments().front();
    2075              :         }
    2076              : 
    2077            0 :         Segment* nextSegment = this->next1MMenabled();
    2078            0 :         while (nextSegment) {
    2079            0 :             if (EngravingItem* annotation = nextSegment->firstAnnotation(activeStaff)) {
    2080            0 :                 return annotation;
    2081              :             }
    2082              : 
    2083            0 :             EngravingItem* nextEl = nextSegment->firstElementOfSegment(activeStaff);
    2084            0 :             if (nextEl) {
    2085            0 :                 return nextEl;
    2086              :             }
    2087            0 :             nextSegment = nextSegment->next1MMenabled();
    2088              :         }
    2089            0 :         break;
    2090              :     }
    2091            0 :     default: {
    2092              :         EngravingItem* p;
    2093            0 :         if (e->isTieSegment() || e->isGlissandoSegment() || e->isGuitarBendSegment()) {
    2094            0 :             SpannerSegment* s = toSpannerSegment(e);
    2095            0 :             Spanner* sp = s->spanner();
    2096            0 :             p = sp->startElement();
    2097              :         } else {
    2098            0 :             p = e;
    2099            0 :             EngravingItem* pp = p->ownershipParentItem();
    2100            0 :             if (pp->isNote() || pp->isRest() || (pp->isChord() && !p->isNote())) {
    2101            0 :                 p = pp;
    2102              :             }
    2103              :         }
    2104            0 :         EngravingItem* el = p;
    2105            0 :         for (; p && !p->isSegment(); p = p->layoutParent()) {
    2106              :         }
    2107            0 :         Segment* seg = toSegment(p);
    2108              :         // next in _elist
    2109            0 :         EngravingItem* nextEl = seg->nextElementOfSegment(el, activeStaff);
    2110            0 :         if (nextEl) {
    2111            0 :             return nextEl;
    2112              :         }
    2113            0 :         if (!m_annotations.empty()) {
    2114            0 :             EngravingItem* next = seg->firstAnnotation(activeStaff);
    2115            0 :             if (next) {
    2116            0 :                 if (next->isStaffText()) {
    2117            0 :                     if (SoundFlag* soundFlag = toStaffText(next)->soundFlag()) {
    2118            0 :                         return soundFlag;
    2119              :                     }
    2120              :                 }
    2121            0 :                 if (next->isFretDiagram()) {
    2122            0 :                     if (Harmony* harmony = toFretDiagram(next)->harmony()) {
    2123            0 :                         return harmony;
    2124              :                     }
    2125              :                 }
    2126              : 
    2127            0 :                 return next;
    2128              :             }
    2129              :         }
    2130            0 :         Spanner* s = firstSpanner(activeStaff);
    2131            0 :         if (s) {
    2132            0 :             return s->spannerSegments().front();
    2133              :         }
    2134              : 
    2135            0 :         for (SpannerSegment* spannerSeg : system()->spannerSegments()) {
    2136            0 :             if (spannerSeg->staffIdx() == activeStaff && spannerSeg->isHammerOnPullOffSegment()) {
    2137            0 :                 for (HammerOnPullOffText* hopoText : toHammerOnPullOffSegment(spannerSeg)->hopoText()) {
    2138            0 :                     if (hopoText->startChord() && hopoText->startChord()->segment() == this) {
    2139            0 :                         return hopoText;
    2140              :                     }
    2141              :                 }
    2142              :             }
    2143              :         }
    2144              : 
    2145            0 :         Segment* nextSegment = seg->next1MMenabled();
    2146            0 :         for (; nextSegment && nextSegment->isTimeTickType(); nextSegment = nextSegment->next1MMenabled()) {
    2147            0 :             if (EngravingItem* annotation = nextSegment->firstAnnotation(activeStaff)) {
    2148            0 :                 return annotation;
    2149              :             }
    2150            0 :             if (Spanner* spanner = nextSegment->firstSpanner(activeStaff)) {
    2151            0 :                 return spanner->spannerSegments().front();
    2152              :             }
    2153              :         }
    2154            0 :         if (!nextSegment) {
    2155            0 :             MeasureBase* mb = measure()->next();
    2156            0 :             return mb && mb->isBox() ? mb : Navigation::lastElement(score());
    2157              :         }
    2158              : 
    2159            0 :         Measure* nsm = nextSegment->measure();
    2160            0 :         if (nsm != measure()) {
    2161              :             // check for frame, measure elements
    2162            0 :             MeasureBase* nmb = measure()->nextMM();
    2163            0 :             EngravingItem* nme = nsm->el().empty() ? nullptr : nsm->el().front();
    2164            0 :             if (nsm != nmb) {
    2165            0 :                 return nmb;
    2166            0 :             } else if (nme && nme->isTextBase() && nme->staffIdx() == e->staffIdx()) {
    2167            0 :                 return nme;
    2168            0 :             } else if (nme && nme->isLayoutBreak() && e->staffIdx() == 0) {
    2169            0 :                 return nme;
    2170            0 :             } else if (nmb->isEndOfSystemLock()) {
    2171            0 :                 System* system = nmb->system();
    2172            0 :                 if (system) {
    2173            0 :                     for (SystemLockIndicator* lockInd : system->systemLockIndicators()) {
    2174            0 :                         if (nmb->systemLock() == lockInd->systemLock()) {
    2175            0 :                             return lockInd;
    2176              :                         }
    2177            0 :                     }
    2178              :                 }
    2179            0 :             } else if (nmb->isEndOfPageLock()) {
    2180            0 :                 System* system = nmb->system();
    2181            0 :                 PageLockIndicator* pli = system ? system->pageLockIndicator() : nullptr;
    2182            0 :                 if (pli) {
    2183            0 :                     return pli;
    2184              :                 }
    2185              :             } //TODO: StaffVisibilityIndicator handling
    2186              :         }
    2187              : 
    2188            0 :         while (nextSegment) {
    2189            0 :             nextEl = nextSegment->firstElementOfSegment(activeStaff);
    2190            0 :             if (nextEl) {
    2191            0 :                 return nextEl;
    2192              :             }
    2193              : 
    2194            0 :             if (EngravingItem* annotation = nextSegment->firstAnnotation(activeStaff)) {
    2195            0 :                 return annotation;
    2196              :             }
    2197              : 
    2198            0 :             nextSegment = nextSegment->next1MMenabled();
    2199              :         }
    2200              :     }
    2201            0 :     break;
    2202              :     }
    2203            0 :     return nullptr;
    2204              : }
    2205              : 
    2206              : //---------------------------------------------------------
    2207              : //   prevElement
    2208              : //---------------------------------------------------------
    2209              : 
    2210            0 : EngravingItem* Segment::prevElement(staff_idx_t activeStaff)
    2211              : {
    2212            0 :     EngravingItem* e = score()->selection().element();
    2213            0 :     if (!e && !score()->selection().elements().empty()) {
    2214            0 :         e = score()->selection().elements().back();
    2215              :     }
    2216            0 :     if (!e) {
    2217            0 :         return nullptr;
    2218              :     }
    2219            0 :     switch (e->type()) {
    2220            0 :     case ElementType::DYNAMIC:
    2221              :     case ElementType::EXPRESSION:
    2222              :     case ElementType::HARMONY:
    2223              :     case ElementType::SYMBOL:
    2224              :     case ElementType::FERMATA:
    2225              :     case ElementType::FRET_DIAGRAM:
    2226              :     case ElementType::TEMPO_TEXT:
    2227              :     case ElementType::STAFF_TEXT:
    2228              :     case ElementType::STAVE_SHARING_LABEL:
    2229              :     case ElementType::SOUND_FLAG:
    2230              :     case ElementType::SYSTEM_TEXT:
    2231              :     case ElementType::TRIPLET_FEEL:
    2232              :     case ElementType::PLAYTECH_ANNOTATION:
    2233              :     case ElementType::CAPO:
    2234              :     case ElementType::STRING_TUNINGS:
    2235              :     case ElementType::REHEARSAL_MARK:
    2236              :     case ElementType::MARKER:
    2237              :     case ElementType::IMAGE:
    2238              :     case ElementType::TEXT:
    2239              :     case ElementType::TREMOLOBAR:
    2240              :     case ElementType::TAB_DURATION_SYMBOL:
    2241              :     case ElementType::FIGURED_BASS:
    2242              :     case ElementType::STAFF_STATE:
    2243              :     case ElementType::INSTRUMENT_CHANGE:
    2244              :     case ElementType::HARP_DIAGRAM:
    2245              :     case ElementType::STICKING: {
    2246            0 :         if (e->isStaffText()) {
    2247            0 :             if (SoundFlag* soundFlag = toStaffText(e)->soundFlag()) {
    2248            0 :                 return soundFlag;
    2249              :             }
    2250              :         }
    2251              : 
    2252            0 :         EngravingItem* prevAnnotation = nullptr;
    2253            0 :         if (e->ownershipParent() == this) {
    2254            0 :             prevAnnotation = this->prevAnnotation(e);
    2255              :         }
    2256            0 :         if (prevAnnotation) {
    2257            0 :             return prevAnnotation;
    2258            0 :         } else if (const Segment* prevSeg = prev1()) {
    2259            0 :             const Spanner* s = prevSeg->lastSpanner(activeStaff);
    2260            0 :             if (s) {
    2261            0 :                 return s->spannerSegments().back();
    2262              :             }
    2263              :         }
    2264              : 
    2265            0 :         if (notChordRestType()) {
    2266            0 :             EngravingItem* lastEl = lastElementOfSegment(activeStaff);
    2267            0 :             if (lastEl) {
    2268            0 :                 return lastEl;
    2269              :             }
    2270              :         }
    2271            0 :         if (isTimeTickType()) {
    2272            0 :             Segment* prevSeg = prev1MMenabled();
    2273            0 :             return prevSeg ? prevSeg->lastElementOfSegment(activeStaff) : nullptr;
    2274              :         }
    2275            0 :         track_idx_t track = score()->nstaves() * VOICES - 1;
    2276            0 :         Segment* s = this;
    2277            0 :         EngravingItem* el = s->element(track);
    2278            0 :         while (track > 0 && (!el || el->staffIdx() != activeStaff)) {
    2279            0 :             if (s != this) {
    2280            0 :                 if (EngravingItem* annotation = s->lastAnnotation(activeStaff)) {
    2281            0 :                     return annotation;
    2282              :                 }
    2283              :             }
    2284              : 
    2285            0 :             el = s->element(--track);
    2286              : 
    2287            0 :             if (track == 0) {
    2288            0 :                 track = score()->nstaves() * VOICES - 1;
    2289            0 :                 s = s->prev1MMenabled();
    2290              :             }
    2291              :         }
    2292            0 :         if (el->staffIdx() != activeStaff) {
    2293            0 :             return nullptr;
    2294              :         }
    2295            0 :         if (el->isChordRest()) {
    2296            0 :             ChordRest* cr = this->cr(el->track());
    2297            0 :             if (cr) {
    2298            0 :                 EngravingItem* elCr = cr->lastElementBeforeSegment();
    2299            0 :                 if (elCr) {
    2300            0 :                     return elCr;
    2301              :                 }
    2302              :             }
    2303              :         }
    2304            0 :         if (el->isChord()) {
    2305            0 :             return toChord(el)->lastElementBeforeSegment();
    2306            0 :         } else if (el->isNote()) {
    2307            0 :             Chord* c = toNote(el)->chord();
    2308            0 :             return c->lastElementBeforeSegment();
    2309              :         } else {
    2310            0 :             return el;
    2311              :         }
    2312              :     }
    2313            0 :     case ElementType::ARPEGGIO:
    2314              :     case ElementType::CHORD_BRACKET:
    2315              :     case ElementType::TREMOLO_SINGLECHORD:
    2316              :     case ElementType::TREMOLO_TWOCHORD: {
    2317            0 :         EngravingItem* el = this->element(e->track());
    2318            0 :         assert(el->isChord());
    2319            0 :         return toChord(el)->prevElement();
    2320              :     }
    2321            0 :     default: {
    2322            0 :         EngravingItem* el = e;
    2323            0 :         Segment* seg = this;
    2324            0 :         if (e->isTieSegment() || e->isGlissandoSegment() || e->isNoteLineSegment()) {
    2325            0 :             SpannerSegment* s = toSpannerSegment(e);
    2326            0 :             Spanner* sp = s->spanner();
    2327            0 :             el = sp->startElement();
    2328            0 :             seg = sp->startSegment();
    2329              :         } else {
    2330            0 :             EngravingItem* ep = e->ownershipParentItem();
    2331            0 :             if (ep->isNote() || ep->isRest() || (ep->isChord() && !e->isNote())) {
    2332            0 :                 el = e->ownershipParentItem();
    2333              :             }
    2334              :         }
    2335              : 
    2336            0 :         EngravingItem* prev = seg->prevElementOfSegment(el, activeStaff);
    2337            0 :         if (prev) {
    2338            0 :             if (prev->isChordRest()) {
    2339            0 :                 ChordRest* cr = seg->cr(prev->track());
    2340            0 :                 if (cr) {
    2341            0 :                     EngravingItem* elCr = cr->lastElementBeforeSegment();
    2342            0 :                     if (elCr) {
    2343            0 :                         return elCr;
    2344              :                     }
    2345              :                 }
    2346              :             }
    2347            0 :             if (prev->isChord()) {
    2348            0 :                 return toChord(prev)->lastElementBeforeSegment();
    2349            0 :             } else if (prev->isNote()) {
    2350            0 :                 Chord* c = toNote(prev)->chord();
    2351            0 :                 return c->lastElementBeforeSegment();
    2352              :             } else {
    2353            0 :                 return prev;
    2354              :             }
    2355              :         } else {
    2356            0 :             System* system = seg->system();
    2357            0 :             for (SpannerSegment* spannerSeg : system->spannerSegments()) {
    2358            0 :                 if (spannerSeg->staffIdx() == activeStaff && spannerSeg->isHammerOnPullOffSegment()) {
    2359            0 :                     for (HammerOnPullOffText* hopoText : toHammerOnPullOffSegment(spannerSeg)->hopoText()) {
    2360            0 :                         if (hopoText->endChord() && hopoText->endChord()->segment() == seg) {
    2361            0 :                             return hopoText;
    2362              :                         }
    2363              :                     }
    2364              :                 }
    2365              :             }
    2366              :         }
    2367              : 
    2368            0 :         Segment* prevSeg = seg->prev1MMenabled();
    2369            0 :         for (; prevSeg && prevSeg->isTimeTickType(); prevSeg = prevSeg->prev1MMenabled()) {
    2370            0 :             if (Spanner* spanner = prevSeg->lastSpanner(activeStaff)) {
    2371            0 :                 return spanner->spannerSegments().front();
    2372              :             }
    2373            0 :             if (EngravingItem* annotation = prevSeg->lastAnnotation(activeStaff)) {
    2374            0 :                 return annotation;
    2375              :             }
    2376              :         }
    2377            0 :         if (!prevSeg) {
    2378            0 :             MeasureBase* mb = measure()->prev();
    2379            0 :             return mb && mb->isBox() ? mb : Navigation::firstElement(score());
    2380              :         }
    2381              : 
    2382            0 :         Measure* psm = prevSeg->measure();
    2383            0 :         if (psm != measure()) {
    2384              :             // check for frame, measure elements
    2385            0 :             MeasureBase* pmb = measure()->prevMM();
    2386            0 :             EngravingItem* me = measure()->el().empty() ? nullptr : measure()->el().back();
    2387            0 :             if (me && me->isTextBase() && me->staffIdx() == e->staffIdx()) {
    2388            0 :                 return me;
    2389            0 :             } else if (me && me->isLayoutBreak() && e->staffIdx() == 0) {
    2390            0 :                 return me;
    2391            0 :             } else if (measure()->isEndOfPageLock()) {
    2392            0 :                 System* system = measure()->system();
    2393            0 :                 PageLockIndicator* pli = system ? system->pageLockIndicator() : nullptr;
    2394            0 :                 if (pli) {
    2395            0 :                     return pli;
    2396              :                 }
    2397            0 :             } else if (measure()->isEndOfSystemLock()) {
    2398            0 :                 System* system = measure()->system();
    2399            0 :                 if (system) {
    2400            0 :                     for (SystemLockIndicator* lockInd : system->systemLockIndicators()) {
    2401            0 :                         if (measure()->systemLock() == lockInd->systemLock()) {
    2402            0 :                             return lockInd;
    2403              :                         }
    2404            0 :                     }
    2405              :                 }
    2406            0 :             } else if (psm != pmb) {
    2407            0 :                 return pmb;
    2408              :             } //TODO: StaffVisibilityIndicator handling
    2409              :         }
    2410              : 
    2411            0 :         if (EngravingItem* annotation = prevSeg->lastAnnotation(activeStaff)) {
    2412            0 :             return annotation;
    2413              :         }
    2414            0 :         if (!prev) {
    2415            0 :             prev = prevSeg->lastElementOfSegment(activeStaff);
    2416              :         }
    2417              : 
    2418            0 :         while (!prev && prevSeg) {
    2419            0 :             prevSeg = prevSeg->prev1MMenabled();
    2420              : 
    2421            0 :             if (EngravingItem* annotation = prevSeg->lastAnnotation(activeStaff)) {
    2422            0 :                 prev = annotation;
    2423              :             } else {
    2424            0 :                 prev = prevSeg->lastElementOfSegment(activeStaff);
    2425              :             }
    2426              :         }
    2427            0 :         if (!prevSeg) {
    2428            0 :             return Navigation::firstElement(score());
    2429              :         }
    2430              : 
    2431            0 :         if (prevSeg->notChordRestType()) {
    2432            0 :             EngravingItem* lastEl = prevSeg->lastElementOfSegment(activeStaff);
    2433            0 :             if (lastEl) {
    2434            0 :                 return lastEl;
    2435              :             }
    2436              :         }
    2437            0 :         Spanner* s1 = prevSeg->lastSpanner(activeStaff);
    2438            0 :         if (s1) {
    2439            0 :             return s1->spannerSegments().front();
    2440            0 :         } else if (!prevSeg->annotations().empty()) {
    2441            0 :             EngravingItem* next = prevSeg->lastAnnotation(activeStaff);
    2442            0 :             if (next) {
    2443            0 :                 return next;
    2444              :             }
    2445              :         }
    2446            0 :         if (prev->isChordRest() || prev->isNote()) {
    2447            0 :             ChordRest* cr = prevSeg->cr(prev->track());
    2448            0 :             if (cr) {
    2449            0 :                 EngravingItem* elCr = cr->lastElementBeforeSegment();
    2450            0 :                 if (elCr) {
    2451            0 :                     return elCr;
    2452              :                 }
    2453              :             }
    2454              :         }
    2455            0 :         if (prev->isChord()) {
    2456            0 :             return toChord(prev)->lastElementBeforeSegment();
    2457            0 :         } else if (prev->isNote()) {
    2458            0 :             Chord* c = toNote(prev)->chord();
    2459            0 :             return c->lastElementBeforeSegment();
    2460              :         } else {
    2461            0 :             return prev;
    2462              :         }
    2463              :     }
    2464              :     }
    2465              : }
    2466              : 
    2467           11 : EngravingItem* Segment::firstElement(staff_idx_t staffIdx) const
    2468              : {
    2469           11 :     track_idx_t startTrack = staffIdx * VOICES;
    2470           11 :     track_idx_t endTrack = startTrack + VOICES;
    2471           43 :     for (track_idx_t track =  startTrack; track < endTrack; ++track) {
    2472           35 :         if (EngravingItem* item = m_elist[track]) {
    2473            3 :             return item;
    2474              :         }
    2475              :     }
    2476            8 :     return nullptr;
    2477              : }
    2478              : 
    2479              : //--------------------------------------------------------
    2480              : //   lastInPrevSegments
    2481              : //   Searches for the previous segment that has elements on
    2482              : //   the active staff and returns its last element
    2483              : //
    2484              : //   Uses lastElement so it also returns a barline if it
    2485              : //   spans into the active staff
    2486              : //--------------------------------------------------------
    2487              : 
    2488           29 : EngravingItem* Segment::lastInPrevSegments(staff_idx_t activeStaff) const
    2489              : {
    2490           29 :     EngravingItem* re = 0;
    2491           29 :     const Segment* seg = this;
    2492              : 
    2493           58 :     while (!re) {
    2494           29 :         seg = seg->prev1MMenabled();
    2495           29 :         if (!seg) {   //end of staff, or score
    2496            0 :             break;
    2497              :         }
    2498              : 
    2499           29 :         re = seg->lastElementOfSegment(activeStaff);
    2500              :     }
    2501              : 
    2502           29 :     if (re) {
    2503           29 :         return re;
    2504              :     }
    2505              : 
    2506            0 :     if (!seg) {   //end of staff
    2507            0 :         if (activeStaff == 0) {   //end of score
    2508            0 :             return 0;
    2509              :         }
    2510              : 
    2511            0 :         re = 0;
    2512            0 :         seg = score()->lastSegmentMM();
    2513              :         while (true) {
    2514              :             //if (seg->segmentType() == SegmentType::EndBarLine)
    2515              :             //      score()->inputState().setTrack((activeStaff - 1) * VOICES ); //correction
    2516              : 
    2517            0 :             if ((re = seg->lastElementForNavigation(activeStaff - 1)) != 0) {
    2518            0 :                 return re;
    2519              :             }
    2520              : 
    2521            0 :             seg = seg->prev1MMenabled();
    2522              :         }
    2523              :     }
    2524              : 
    2525            0 :     return 0;
    2526              : }
    2527              : 
    2528              : //---------------------------------------------------------
    2529              : //   accessibleExtraInfo
    2530              : //---------------------------------------------------------
    2531              : 
    2532            0 : String Segment::accessibleExtraInfo() const
    2533              : {
    2534            0 :     String rez;
    2535            0 :     if (!annotations().empty()) {
    2536            0 :         String temp;
    2537            0 :         for (const EngravingItem* a : annotations()) {
    2538            0 :             if (!score()->selectionFilter().canSelect(a)) {
    2539            0 :                 continue;
    2540              :             }
    2541            0 :             switch (a->type()) {
    2542            0 :             case ElementType::DYNAMIC:
    2543              :                 //they are added in the chordrest, because they are for only one staff
    2544            0 :                 break;
    2545            0 :             default:
    2546            0 :                 temp = temp + u' ' + a->accessibleInfo();
    2547              :             }
    2548              :         }
    2549            0 :         if (!temp.isEmpty()) {
    2550            0 :             rez = rez + muse::mtrc("engraving", "Annotations:") + temp;
    2551              :         }
    2552            0 :     }
    2553              : 
    2554            0 :     String startSpanners;
    2555            0 :     String endSpanners;
    2556              : 
    2557            0 :     auto spanners = score()->spannerMap().findOverlapping(tick().ticks(), tick().ticks());
    2558            0 :     for (auto interval : spanners) {
    2559            0 :         Spanner* s = interval.value;
    2560            0 :         if (!score()->selectionFilter().canSelect(s)) {
    2561            0 :             continue;
    2562              :         }
    2563            0 :         if (segmentType() == SegmentType::EndBarLine
    2564            0 :             || segmentType() == SegmentType::BarLine
    2565            0 :             || segmentType() == SegmentType::StartRepeatBarLine) {
    2566            0 :             if (s->isVolta()) {
    2567            0 :                 continue;
    2568              :             }
    2569              :         } else {
    2570            0 :             if (s->isVolta() || s->isTie()) {     //ties are added in Note
    2571            0 :                 continue;
    2572              :             }
    2573              :         }
    2574              : 
    2575            0 :         if (s->tick() == tick()) {
    2576            0 :             startSpanners += u" " + muse::mtrc("engraving", "Start of %1").arg(s->accessibleInfo());
    2577              :         }
    2578              : 
    2579            0 :         const Segment* seg = 0;
    2580            0 :         switch (s->type()) {
    2581            0 :         case ElementType::VOLTA:
    2582              :         case ElementType::SLUR:
    2583            0 :             seg = this;
    2584            0 :             break;
    2585            0 :         default:
    2586            0 :             seg = next1MM(SegmentType::ChordRest);
    2587            0 :             break;
    2588              :         }
    2589              : 
    2590            0 :         if (seg && s->tick2() == seg->tick()) {
    2591            0 :             endSpanners += u" " + muse::mtrc("engraving", "End of %1").arg(s->accessibleInfo());
    2592              :         }
    2593              :     }
    2594              : 
    2595            0 :     return rez + startSpanners + endSpanners;
    2596            0 : }
    2597              : 
    2598              : //---------------------------------------------------------
    2599              : //   createShapes
    2600              : //---------------------------------------------------------
    2601              : 
    2602       355586 : void Segment::createShapes()
    2603              : {
    2604       355586 :     setVisible(false);
    2605       880742 :     for (size_t staffIdx = 0; staffIdx < score()->nstaves(); ++staffIdx) {
    2606       525156 :         createShape(staffIdx);
    2607              :     }
    2608       355586 : }
    2609              : 
    2610              : //---------------------------------------------------------
    2611              : //   createShape
    2612              : //---------------------------------------------------------
    2613              : 
    2614       557427 : void Segment::createShape(staff_idx_t staffIdx)
    2615              : {
    2616       557427 :     Shape& s = m_shapes[staffIdx];
    2617       557427 :     s.clear();
    2618              : 
    2619       557427 :     if (const System* system = this->system()) {
    2620       557384 :         const std::vector<SysStaff*>& staves = system->staves();
    2621              : 
    2622       557384 :         if (staffIdx < staves.size() && !staves[staffIdx]->show()) {
    2623         8491 :             return;
    2624              :         }
    2625              :     }
    2626              : 
    2627       548936 :     if (!score()->staff(staffIdx)->show()) {
    2628            0 :         return;
    2629              :     }
    2630              : 
    2631       548936 :     track_idx_t strack = staffIdx * VOICES;
    2632       548936 :     track_idx_t etrack = strack + VOICES;
    2633      8022168 :     for (EngravingItem* e : m_elist) {
    2634      7473232 :         if (!e) {
    2635      5629885 :             continue;
    2636              :         }
    2637      1843347 :         track_idx_t effectiveTrack = e->vStaffIdx() * VOICES + e->voice();
    2638      1843347 :         if (effectiveTrack >= strack && effectiveTrack < etrack) {
    2639       544977 :             setVisible(true);
    2640       544977 :             if (e->isRest() && toRest(e)->isFullMeasureRest() && measure()->hasVoices(e->staffIdx())) {
    2641              :                 // A full measure rest in a measure with multiple voices must be ignored
    2642              :                 // Unless the measure is made of *only* full rests
    2643          722 :                 bool isAllFullRests = true;
    2644         2014 :                 for (track_idx_t track = strack; track < etrack; ++track) {
    2645         1966 :                     EngravingItem* element = m_elist[track];
    2646         1966 :                     if (element && !(element->isRest() && toRest(element)->isFullMeasureRest())) {
    2647          674 :                         isAllFullRests = false;
    2648          674 :                         break;
    2649              :                     }
    2650              :                 }
    2651          722 :                 if (!isAllFullRests) {
    2652          674 :                     continue;
    2653              :                 }
    2654              :             }
    2655       544303 :             if (e->isMMRest() || (e->isMeasureRepeat() && toMeasureRepeat(e)->numMeasures() > 1)) {
    2656         1061 :                 continue;
    2657              :             }
    2658       543242 :             if (e->addToSkyline() || (e->isChordRest() && toChordRest(e)->lyrics().size() > 0)) {
    2659       542369 :                 s.add(e->shape().translate((e->isClef() ? e->ldata()->pos() : e->pos()) + e->staffOffset()));
    2660              :             }
    2661              :             // Non-standard trills display a cue note that we must add to shape here
    2662       543242 :             if (e->isChord()) {
    2663       151659 :                 addArticulationsToShape(toChord(e), s);
    2664              :             }
    2665              :         }
    2666              :     }
    2667              : 
    2668       586685 :     for (EngravingItem* e : m_annotations) {
    2669        37749 :         if (!e || e->staffIdx() != staffIdx) {
    2670        13728 :             continue;
    2671              :         }
    2672              : 
    2673        24021 :         setVisible(true);
    2674              : 
    2675              :         // Still include harmony attached to fret diagram
    2676        24021 :         if (e->isFretDiagram() && !e->addToSkyline() && toFretDiagram(e)->harmony()) {
    2677            0 :             e = toHarmony(toFretDiagram(e)->harmony());
    2678              :         }
    2679              : 
    2680        24021 :         if (!e->addToSkyline()) {
    2681          456 :             continue;
    2682              :         }
    2683              : 
    2684        23565 :         if (e->isHarmony() || e->isFretDiagram()) {
    2685              :             // TODO: eliminate once and for all this addHorizontalSpace hack [M.S.]
    2686         9199 :             PointF pos = e->pos();
    2687              :             // Harmony attached to invisible fret diagram
    2688         9199 :             const EngravingItem* parent = e->layoutParent();
    2689         9199 :             if (e->isHarmony() && parent && parent->isFretDiagram()) {
    2690            0 :                 pos += parent->pos();
    2691              :             }
    2692         9199 :             RectF bbox = e->ldata()->bbox().translated(pos);
    2693         9199 :             if (Parenthesis* p = e->leftParen()) {
    2694            6 :                 bbox.unite(p->ldata()->bbox().translated(p->pos() + pos));
    2695              :             }
    2696         9199 :             if (Parenthesis* p = e->rightParen()) {
    2697            6 :                 bbox.unite(p->ldata()->bbox().translated(p->pos() + pos));
    2698              :             }
    2699         9199 :             s.addHorizontalSpacing(e, bbox.left(), bbox.right());
    2700         9199 :             if (e->isFretDiagram()) {
    2701         1207 :                 if (Harmony* harmony = toFretDiagram(e)->harmony()) {
    2702          853 :                     RectF harmBbox = harmony->ldata()->bbox().translated(harmony->pos() + e->pos());
    2703          853 :                     if (Parenthesis* p = harmony->leftParen()) {
    2704            0 :                         harmBbox.unite(p->ldata()->bbox().translated(p->pos() + harmony->pos() + e->pos()));
    2705              :                     }
    2706          853 :                     if (Parenthesis* p = harmony->rightParen()) {
    2707            0 :                         harmBbox.unite(p->ldata()->bbox().translated(p->pos() + harmony->pos() + e->pos()));
    2708              :                     }
    2709          853 :                     s.addHorizontalSpacing(harmony, harmBbox.left(), harmBbox.right());
    2710              :                 }
    2711              :             }
    2712        14366 :         } else if (!e->isRehearsalMark()
    2713        13910 :                    && !e->isFretDiagram()
    2714        13910 :                    && !e->isHarmony()
    2715        13910 :                    && !e->isTempoText()
    2716        10568 :                    && !e->isDynamic()
    2717         7089 :                    && !e->isExpression()
    2718         6985 :                    && !e->isFiguredBass()
    2719         6508 :                    && !e->isSymbol()
    2720         6439 :                    && !e->isFSymbol()
    2721         6439 :                    && !e->isSystemText()
    2722         6000 :                    && !e->isTripletFeel()
    2723         6000 :                    && !e->isInstrumentChange()
    2724         5708 :                    && !e->isArticulationFamily()
    2725         5708 :                    && !e->isStaffText()
    2726         2107 :                    && !e->isHarpPedalDiagram()
    2727         1981 :                    && !e->isPlayTechAnnotation()
    2728         1709 :                    && !e->isCapo()
    2729         1577 :                    && !e->isStringTunings()
    2730        28276 :                    && !e->isPlayCountText()) {
    2731              :             // annotations added here are candidates for collision detection
    2732         1500 :             s.add(e->shape().translate(e->pos() + e->staffOffset()));
    2733              :         }
    2734              :     }
    2735              : 
    2736      2744680 :     for (track_idx_t track = strack; track < etrack; ++track) {
    2737      2195744 :         if (!m_preAppendedItems[track]) {
    2738      2194622 :             continue;
    2739              :         }
    2740         1122 :         EngravingItem* item = m_preAppendedItems[track];
    2741         1122 :         if (item->isGraceNotesGroup()) {
    2742         1122 :             toGraceNotesGroup(item)->addToShape();
    2743              :         } else {
    2744            0 :             Shape& shape = m_shapes[item->vStaffIdx()];
    2745            0 :             shape.add(item->shape().translate(item->pos() + item->staffOffset()));
    2746              :         }
    2747              :     }
    2748              : }
    2749              : 
    2750       151659 : void Segment::addArticulationsToShape(const Chord* chord, Shape& shape)
    2751              : {
    2752           40 :     auto addTappingHalfSlurToShape = [&] (TappingHalfSlur* slur) {
    2753           40 :         IF_ASSERT_FAILED(!slur->segmentsEmpty()) {
    2754            0 :             return;
    2755              :         }
    2756           40 :         TappingHalfSlurSegment* slurSeg = toTappingHalfSlurSegment(slur->frontSegment());
    2757           40 :         Shape slurSegShape = slurSeg->shape();
    2758              :         // Semi-hack: we don't know the exact position at this stage, but we know that it
    2759              :         // must end approx on the center of the notehead
    2760           40 :         Note* note = slur->up() ? chord->upNote() : chord->downNote();
    2761           40 :         double approxPosX = chord->x() + note->x() + 0.5 * note->headWidth() - slurSegShape.right();
    2762           40 :         slurSegShape.translateX(approxPosX);
    2763           40 :         shape.add(slurSegShape);
    2764           40 :     };
    2765              : 
    2766       156843 :     for (Articulation* art : chord->articulations()) {
    2767         5184 :         if (art->isOrnament() || !art->addToSkyline()) {
    2768          997 :             continue;
    2769              :         }
    2770         4187 :         shape.add(art->shape().translated(art->pos() + chord->pos()));
    2771         4187 :         if (art->isTapping()) {
    2772          201 :             if (TappingHalfSlur* halfSlur = toTapping(art)->halfSlurAbove()) {
    2773           40 :                 addTappingHalfSlurToShape(halfSlur);
    2774              :             }
    2775          201 :             if (TappingHalfSlur* halfSlur = toTapping(art)->halfSlurBelow()) {
    2776            0 :                 addTappingHalfSlurToShape(halfSlur);
    2777              :             }
    2778              :         }
    2779              :     }
    2780              : 
    2781       151659 :     Ornament* ornament = chord->findOrnament();
    2782       151659 :     if (ornament) {
    2783         1178 :         Chord* cueNoteChord = ornament->cueNoteChord();
    2784         1178 :         if (cueNoteChord && cueNoteChord->upNote()->addToSkyline()) {
    2785           49 :             shape.add(cueNoteChord->shape().translate(cueNoteChord->pos() + cueNoteChord->staffOffset()));
    2786              :         }
    2787              :     }
    2788       151659 : }
    2789              : 
    2790              : //---------------------------------------------------------
    2791              : //   minRight
    2792              : //    calculate minimum distance needed to the right
    2793              : //---------------------------------------------------------
    2794              : 
    2795       221943 : double Segment::minRight() const
    2796              : {
    2797       221943 :     double distance = 0.0;
    2798       661350 :     for (Shape sh : shapes()) {
    2799       971702 :         sh.remove_if([](ShapeElement& el) { return el.item() && el.item()->isArticulationOrFermata(); });
    2800       439407 :         distance = std::max(distance, sh.right());
    2801       439407 :     }
    2802       221943 :     return distance;
    2803              : }
    2804              : 
    2805        89329 : double Segment::minLeft() const
    2806              : {
    2807        89329 :     double distance = DBL_MAX;
    2808       286562 :     for (Shape sh : shapes()) {
    2809       504847 :         sh.remove_if([](ShapeElement& el) { return el.item() && el.item()->isArticulationOrFermata(); });
    2810       197233 :         double l = sh.left();
    2811       197233 :         if (l < distance) {
    2812        91139 :             distance = l;
    2813              :         }
    2814       197233 :     }
    2815        89329 :     return distance != DBL_MAX ? -distance : 0.0;
    2816              : }
    2817              : 
    2818            0 : void Segment::setSpacing(double val)
    2819              : {
    2820            0 :     m_spacing = val;
    2821            0 : }
    2822              : 
    2823            0 : double Segment::spacing() const
    2824              : {
    2825            0 :     return m_spacing;
    2826              : }
    2827              : 
    2828      1227627 : bool Segment::hasTimeSigAboveStaves() const
    2829              : {
    2830      1227627 :     return isType(SegmentType::TimeSigTypes)
    2831      1227627 :            && style().styleV(Sid::timeSigPlacement).value<TimeSigPlacement>() == TimeSigPlacement::ABOVE_STAVES;
    2832              : }
    2833              : 
    2834            0 : bool Segment::makeSpaceForTimeSigAboveStaves() const
    2835              : {
    2836            0 :     bool makeSpace = style().styleB(Sid::timeSigCenterOnBarline)
    2837            0 :                      ? style().styleV(Sid::timeSigVSMarginCentered).value<TimeSigVSMargin>() == TimeSigVSMargin::CREATE_SPACE
    2838            0 :                      : style().styleV(Sid::timeSigVSMarginNonCentered).value<TimeSigVSMargin>() == TimeSigVSMargin::CREATE_SPACE;
    2839            0 :     return hasTimeSigAboveStaves() && makeSpace;
    2840              : }
    2841              : 
    2842            0 : bool Segment::hasTimeSigAcrossStaves() const
    2843              : {
    2844            0 :     return isType(SegmentType::TimeSigTypes)
    2845            0 :            && style().styleV(Sid::timeSigPlacement).value<TimeSigPlacement>() == TimeSigPlacement::ACROSS_STAVES;
    2846              : }
    2847              : 
    2848            0 : bool Segment::canWriteSpannerStartEnd(track_idx_t track, const Spanner* spanner) const
    2849              : {
    2850            0 :     staff_idx_t staffIdx = track2staff(track);
    2851            0 :     if (isChordRestType() && (element(track) || (!spanner->isVoiceSpecific() && hasElements(staffIdx)))) {
    2852            0 :         return true;
    2853              :     }
    2854              : 
    2855            0 :     if (isTimeTickType()) {
    2856              :         Segment* crSegAtSameTick
    2857            0 :             = score()->tick2segment(tick(), true, SegmentType::ChordRest, style().styleB(Sid::createMultiMeasureRests));
    2858            0 :         if (!crSegAtSameTick || !crSegAtSameTick->canWriteSpannerStartEnd(track, spanner)) {
    2859            0 :             return true;
    2860              :         }
    2861              :     }
    2862              : 
    2863            0 :     return score()->lastMeasure()->last() == this;
    2864              : }
    2865              : 
    2866            0 : double Segment::elementsTopOffsetFromSkyline(staff_idx_t staffIndex) const
    2867              : {
    2868            0 :     System* segmentSystem = measure()->system();
    2869            0 :     SysStaff* staffSystem = segmentSystem ? segmentSystem->staff(staffIndex) : nullptr;
    2870              : 
    2871            0 :     if (!staffSystem) {
    2872            0 :         return 0;
    2873              :     }
    2874              : 
    2875            0 :     SkylineLine north = staffSystem->skyline().north();
    2876            0 :     int topOffset = INT_MAX;
    2877            0 :     for (const ShapeElement& element : north.elements()) {
    2878            0 :         Segment* seg = prev1enabled();
    2879            0 :         if (!seg) {
    2880            0 :             continue;
    2881              :         }
    2882            0 :         bool ok = seg->pagePos().x() <= element.left() && element.left() <= pagePos().x();
    2883            0 :         if (!ok) {
    2884            0 :             continue;
    2885              :         }
    2886              : 
    2887            0 :         if (element.top() < topOffset) {
    2888            0 :             topOffset = element.top();
    2889              :         }
    2890              :     }
    2891              : 
    2892            0 :     if (topOffset == INT_MAX) {
    2893            0 :         topOffset = 0;
    2894              :     }
    2895              : 
    2896            0 :     return topOffset;
    2897            0 : }
    2898              : 
    2899            0 : double Segment::elementsBottomOffsetFromSkyline(staff_idx_t staffIndex) const
    2900              : {
    2901            0 :     System* segmentSystem = measure()->system();
    2902            0 :     SysStaff* staffSystem = segmentSystem ? segmentSystem->staff(staffIndex) : nullptr;
    2903              : 
    2904            0 :     if (!staffSystem) {
    2905            0 :         return 0;
    2906              :     }
    2907              : 
    2908            0 :     SkylineLine south = staffSystem->skyline().south();
    2909            0 :     int bottomOffset = INT_MIN;
    2910            0 :     for (const ShapeElement& element : south.elements()) {
    2911            0 :         Segment* seg = prev1enabled();
    2912            0 :         if (!seg) {
    2913            0 :             continue;
    2914              :         }
    2915            0 :         bool ok = seg->pagePos().x() <= element.left() && element.left() <= pagePos().x();
    2916            0 :         if (!ok) {
    2917            0 :             continue;
    2918              :         }
    2919              : 
    2920            0 :         if (element.bottom() > bottomOffset) {
    2921            0 :             bottomOffset = element.bottom();
    2922              :         }
    2923              :     }
    2924              : 
    2925            0 :     if (bottomOffset == INT_MIN) {
    2926            0 :         bottomOffset = staffSystem->bbox().height();
    2927              :     }
    2928              : 
    2929            0 :     return bottomOffset;
    2930            0 : }
    2931              : 
    2932              : //------------------------------------------------------
    2933              : // shortestChordRest()
    2934              : // returns the shortest chordRest of a segment. IMPORTANT:
    2935              : // this is not the same as the ticks() of the segment. The
    2936              : // actual duration of the segment may be shorter than its
    2937              : // shortest chordRest. Invisible chordRests are ignored.
    2938              : //------------------------------------------------------
    2939       257343 : Fraction Segment::shortestChordRest() const
    2940              : {
    2941       257343 :     Fraction shortest = measure()->ticks(); // Initializing at the highest possible value ( = time signature of the measure)
    2942       257343 :     Fraction cur = measure()->ticks();
    2943      1685727 :     for (auto elem : elist()) {
    2944       355459 :         if (!elem || !elem->staff()->show() || !elem->isChordRest() || (elem->isRest() && toRest(elem)->isGap())
    2945      1784933 :             || (!elem->visible()
    2946         1090 :                 && measure()->hasVoices(elem->staffIdx(), measure()->tick(), measure()->ticks(), /*considerInvisible*/ true))) {
    2947      1076959 :             continue;
    2948              :         }
    2949       351425 :         cur = toChordRest(elem)->actualTicks();
    2950       351425 :         assert(cur.isNotZero());
    2951       351425 :         if (cur < shortest) {
    2952       198649 :             shortest = cur;
    2953              :         }
    2954              :     }
    2955       257343 :     return shortest;
    2956              : }
    2957              : 
    2958        28089 : bool Segment::hasAccidentals() const
    2959              : {
    2960        28089 :     if (!isChordRestType()) {
    2961            0 :         return false;
    2962              :     }
    2963       187480 :     for (EngravingItem* e : elist()) {
    2964       160632 :         if (!e || !e->isChord() || (e->staff() && !e->staff()->show())) {
    2965       137666 :             continue;
    2966              :         }
    2967        48737 :         for (Note* note : toChord(e)->notes()) {
    2968        27012 :             if (note->accidental() && note->accidental()->addToSkyline()) {
    2969         1241 :                 return true;
    2970              :             }
    2971              :         }
    2972              :     }
    2973        26848 :     return false;
    2974              : }
    2975              : 
    2976        45521 : bool Segment::goesBefore(const Segment* nextSegment) const
    2977              : {
    2978        45521 :     Measure* meas = measure();
    2979        45521 :     Measure* prevMeasure = meas->prevMeasure();
    2980        45521 :     const bool thisMeasureIsStartRepeat = meas->repeatStart();
    2981        45521 :     const bool prevMeasureIsEndRepeat = prevMeasure ? prevMeasure->repeatEnd() : false;
    2982              : 
    2983        45521 :     bool thisIsClef = isClefType();
    2984        45521 :     bool nextIsClef = nextSegment->isClefType();
    2985        45521 :     bool thisIsBarline = isType(SegmentType::BarLine | SegmentType::EndBarLine | SegmentType::StartRepeatBarLine);
    2986        45521 :     bool nextIsBarline = nextSegment->isType(SegmentType::BarLine | SegmentType::EndBarLine | SegmentType::StartRepeatBarLine);
    2987              : 
    2988        45521 :     bool thisIsStartRepeat = isStartRepeatBarLineType();
    2989        45521 :     bool nextIsStartRepeat = nextSegment->isStartRepeatBarLineType();
    2990        45521 :     bool thisIsKeySig = isKeySigType();
    2991        45521 :     bool thisIsTimeSig = isTimeSigType();
    2992        45521 :     bool nextIsKeySig = nextSegment->isKeySigType();
    2993        45521 :     bool nextIsTimeSig = nextSegment->isTimeSigType();
    2994              : 
    2995              :     // Place non header clefs AFTER header clefs, key signatures, time signatures
    2996        45521 :     const bool firstSystemMeasure = meas->findSegmentR(SegmentType::HeaderClef, Fraction(0, 1));
    2997        45521 :     bool thisIsHeader = isHeaderClefType() || (rtick() == Fraction(0, 1) && firstSystemMeasure && !thisIsClef);
    2998        45521 :     bool nextIsHeader = nextSegment->isHeaderClefType() || (nextSegment->rtick() == Fraction(0, 1) && firstSystemMeasure && !nextIsClef);
    2999              : 
    3000        45521 :     bool thisIsEndOfMeasure = endOfMeasureChange();
    3001              : 
    3002              :     // Place segments in correct place when "Place all changes before the barline" is enabled
    3003        45521 :     if (thisIsEndOfMeasure && nextSegment->tick() != meas->endTick()) {
    3004            0 :         return false;
    3005              :     }
    3006              : 
    3007        45521 :     if (thisIsEndOfMeasure && nextIsBarline) {
    3008            4 :         return true;
    3009              :     }
    3010              : 
    3011              :     // Place key signatures and time signatures in correct place when "Allow changes between end-start repeats" is enabled
    3012        45517 :     if ((thisIsKeySig || thisIsTimeSig || thisIsClef) && nextIsStartRepeat && thisMeasureIsStartRepeat && prevMeasureIsEndRepeat) {
    3013            9 :         return style().styleB(Sid::changesBetweenEndStartRepeat);
    3014              :     }
    3015        45508 :     if ((nextIsKeySig || nextIsTimeSig || nextIsClef) && thisIsStartRepeat && thisMeasureIsStartRepeat && prevMeasureIsEndRepeat) {
    3016           17 :         return !style().styleB(Sid::changesBetweenEndStartRepeat);
    3017              :     }
    3018              : 
    3019        45491 :     if (thisIsClef && nextIsBarline) {
    3020           11 :         ClefToBarlinePosition clefPos = ClefToBarlinePosition::AUTO;
    3021           67 :         for (EngravingItem* item : elist()) {
    3022           57 :             if (item && item->isClef()) {
    3023            1 :                 clefPos = toClef(item)->clefToBarlinePosition();
    3024            1 :                 break;
    3025              :             }
    3026              :         }
    3027           11 :         return clefPos != ClefToBarlinePosition::AFTER;
    3028              :     }
    3029              : 
    3030        45480 :     if (thisIsBarline && nextIsClef) {
    3031          153 :         ClefToBarlinePosition clefPos = ClefToBarlinePosition::AUTO;
    3032          201 :         for (EngravingItem* item : nextSegment->elist()) {
    3033          200 :             if (item && item->isClef()) {
    3034          152 :                 clefPos = toClef(item)->clefToBarlinePosition();
    3035          152 :                 break;
    3036              :             }
    3037              :         }
    3038          153 :         return clefPos == ClefToBarlinePosition::AFTER;
    3039              :     }
    3040              : 
    3041           33 :     if (thisIsClef && (nextIsKeySig || nextIsTimeSig) && rtick() == Fraction(0, 1) && nextSegment->rtick() == Fraction(0, 1)
    3042        45360 :         && !nextIsHeader && thisMeasureIsStartRepeat && prevMeasureIsEndRepeat) {
    3043              :         // Between repeats
    3044            1 :         return true;
    3045              :     }
    3046              : 
    3047        45326 :     if ((thisIsKeySig || thisIsTimeSig) && nextIsClef && rtick() == Fraction(0, 1) && nextSegment->rtick() == Fraction(0, 1)
    3048        90652 :         && !thisIsHeader && thisMeasureIsStartRepeat && prevMeasureIsEndRepeat) {
    3049              :         // Between repeats
    3050            4 :         return false;
    3051              :     }
    3052              : 
    3053        45322 :     return segmentType() < nextSegment->segmentType();
    3054              : }
    3055              : } // namespace mu::engraving
        

Generated by: LCOV version 2.0-1