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
|