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 "rest.h"
24 :
25 : #include <cmath>
26 : #include <set>
27 :
28 : #include "containers.h"
29 : #include "translation.h"
30 :
31 : #include "iengravingconfiguration.h"
32 :
33 : #include "../editing/addremoveelement.h"
34 : #include "../editing/editchord.h"
35 : #include "../editing/editmeasurerepeat.h"
36 : #include "../editing/noteinput.h"
37 : #include "../editing/transaction/transaction.h"
38 :
39 : #include "articulation.h"
40 : #include "chord.h"
41 : #include "deadslapped.h"
42 : #include "factory.h"
43 : #include "measure.h"
44 : #include "measurerepeat.h"
45 : #include "note.h"
46 : #include "score.h"
47 : #include "segment.h"
48 : #include "staff.h"
49 : #include "stafftype.h"
50 :
51 : #include "log.h"
52 :
53 : using namespace mu;
54 : using namespace mu::engraving;
55 :
56 : namespace mu::engraving {
57 : //---------------------------------------------------------
58 : // Rest
59 : //--------------------------------------------------------
60 :
61 18552 : Rest::Rest(DummyParentOr<Segment> parent)
62 18552 : : Rest(ElementType::REST, parent)
63 : {
64 18552 : }
65 :
66 18793 : Rest::Rest(const ElementType& type, DummyParentOr<Segment> parent)
67 18793 : : ChordRest(type, parent)
68 : {
69 18793 : m_beamMode = BeamMode::NONE;
70 18793 : }
71 :
72 2912 : Rest::Rest(DummyParentOr<Segment> parent, const TDuration& d)
73 2912 : : Rest(ElementType::REST, parent, d)
74 : {
75 2912 : }
76 :
77 2912 : Rest::Rest(const ElementType& type, DummyParentOr<Segment> parent, const TDuration& d)
78 2912 : : ChordRest(type, parent)
79 : {
80 2912 : m_beamMode = BeamMode::NONE;
81 2912 : setDurationType(d);
82 2912 : if (d.fraction().isValid()) {
83 1176 : setTicks(d.fraction());
84 : }
85 2912 : }
86 :
87 1517 : Rest::Rest(const Rest& r, bool link)
88 1517 : : ChordRest(r, link)
89 : {
90 1517 : if (link) {
91 941 : score()->undo(new Link(this, const_cast<Rest*>(&r)));
92 941 : setAutoplace(true);
93 : }
94 1517 : m_gap = r.m_gap;
95 1517 : m_dotline = r.m_dotline;
96 1520 : for (NoteDot* dot : r.m_dots) {
97 3 : add(Factory::copyNoteDot(*dot));
98 : }
99 :
100 1517 : if (r.m_deadSlapped) {
101 0 : DeadSlapped* ndc = Factory::copyDeadSlapped(*r.m_deadSlapped);
102 0 : add(ndc);
103 0 : if (link) {
104 0 : score()->undo(new Link(ndc, r.m_deadSlapped));
105 : }
106 : }
107 1517 : }
108 :
109 1 : void Rest::hack_toRestType()
110 : {
111 1 : hack_setType(ElementType::REST);
112 1 : }
113 :
114 : //---------------------------------------------------------
115 : // setOffset, overridden from EngravingItem
116 : // (- raster vertical position in spatium units) -> no
117 : // - half rests and whole rests outside the staff are
118 : // replaced by special symbols with ledger lines
119 : //---------------------------------------------------------
120 :
121 82 : void Rest::setOffset(const PointF& o)
122 : {
123 82 : double _spatium = spatium();
124 82 : int line = lrint(o.y() / _spatium);
125 :
126 : //! NOTE We need to find out why this is being done here.
127 : //! We rewrite sym in the layout (we get from the Rest::getSymbol method )
128 :
129 82 : LayoutData* ldata = mutldata();
130 :
131 82 : if (ldata->sym == SymId::restWhole && (line <= -2 || line >= 3)) {
132 0 : ldata->sym = SymId::restWholeLegerLine;
133 82 : } else if (ldata->sym == SymId::restWholeLegerLine && (line > -2 && line < 4)) {
134 0 : ldata->sym = SymId::restWhole;
135 82 : } else if (ldata->sym == SymId::restHalf && (line <= -3 || line >= 3)) {
136 0 : ldata->sym = SymId::restHalfLegerLine;
137 82 : } else if (ldata->sym == SymId::restHalfLegerLine && (line > -3 && line < 3)) {
138 0 : ldata->sym = SymId::restHalf;
139 : }
140 :
141 82 : EngravingItem::setOffset(o);
142 82 : }
143 :
144 : //---------------------------------------------------------
145 : // drag
146 : //---------------------------------------------------------
147 :
148 0 : RectF Rest::drag(EditData& ed)
149 : {
150 0 : if (ed.modifiers & ShiftModifier) {
151 0 : Segment* seg = segment();
152 0 : const Spatium deltaSp = Spatium(ed.evtDelta.x() / spatium());
153 0 : seg->undoChangeProperty(Pid::LEADING_SPACE, seg->extraLeadingSpace() + deltaSp);
154 : } else {
155 0 : setOffset(offset() + ed.evtDelta);
156 : }
157 0 : triggerLayout();
158 0 : return RectF();
159 : }
160 :
161 : //---------------------------------------------------------
162 : // acceptDrop
163 : //---------------------------------------------------------
164 :
165 5 : bool Rest::acceptDrop(EditData& data) const
166 : {
167 5 : EngravingItem* e = data.dropElement;
168 :
169 5 : switch (e->type()) {
170 5 : case ElementType::CHORD:
171 : case ElementType::NOTE:
172 : case ElementType::IMAGE:
173 : case ElementType::SYMBOL:
174 5 : return true;
175 0 : case ElementType::MEASURE_REPEAT:
176 0 : return durationType().type() == DurationType::V_MEASURE;
177 0 : default:
178 : // prevent 'hanging' slurs, avoid crash on tie
179 0 : if (e->isSpanner()) {
180 : static const std::set<ElementType> ignoredTypes {
181 : ElementType::SLUR,
182 : ElementType::HAMMER_ON_PULL_OFF,
183 : ElementType::TIE,
184 : ElementType::GLISSANDO
185 0 : };
186 0 : return !muse::contains(ignoredTypes, e->type());
187 : }
188 0 : break;
189 : }
190 0 : return ChordRest::acceptDrop(data);
191 : }
192 :
193 : //---------------------------------------------------------
194 : // drop
195 : //---------------------------------------------------------
196 :
197 9 : EngravingItem* Rest::drop(Transaction& tx, EditData& data)
198 : {
199 9 : EngravingItem* e = data.dropElement;
200 9 : switch (e->type()) {
201 0 : case ElementType::ARTICULATION:
202 : {
203 0 : Articulation* a = toArticulation(e);
204 0 : if (!a->isFermata() || !EditChord::toggleArticulation(score(), this, a)) {
205 0 : delete e;
206 0 : e = nullptr;
207 : }
208 : }
209 0 : return e;
210 :
211 0 : case ElementType::CHORD: {
212 0 : Chord* c = toChord(e);
213 0 : Note* n = c->upNote();
214 0 : DirectionV dir = c->stemDirection();
215 0 : NoteVal nval;
216 0 : nval.pitch = n->pitch();
217 0 : nval.headGroup = n->headGroup();
218 0 : Fraction d = score()->inputState().ticks();
219 0 : if (!d.isZero()) {
220 0 : Segment* seg = score()->setNoteRest(segment(), track(), nval, d, dir);
221 0 : if (seg) {
222 0 : const ChordRest* cr = toChordRest(seg->element(track()));
223 0 : if (cr) {
224 0 : NoteInput::nextInputPos(tx, score(), cr, false);
225 : }
226 : }
227 : }
228 0 : delete e;
229 : }
230 0 : break;
231 0 : case ElementType::MEASURE_REPEAT: {
232 0 : int numMeasures = toMeasureRepeat(e)->numMeasures();
233 0 : delete e;
234 0 : if (durationType().type() == DurationType::V_MEASURE) {
235 0 : EditMeasureRepeat::addMeasureRepeat(tx, score(), measure(), numMeasures, staffIdx());
236 : }
237 0 : break;
238 : }
239 :
240 9 : default:
241 9 : return ChordRest::drop(tx, data);
242 : }
243 0 : return 0;
244 : }
245 :
246 : //---------------------------------------------------------
247 : // getSymbol
248 : //---------------------------------------------------------
249 :
250 66899 : SymId Rest::getSymbol(DurationType type, int line, int lines) const
251 : {
252 66899 : switch (type) {
253 4 : case DurationType::V_LONG:
254 4 : return SymId::restLonga;
255 0 : case DurationType::V_BREVE:
256 0 : return (line < 0 || line >= lines) ? SymId::restDoubleWholeLegerLine : SymId::restDoubleWhole;
257 55715 : case DurationType::V_MEASURE:
258 55715 : if (ticks() >= Fraction(2, 1)) {
259 0 : return (line < 0 || line >= lines) ? SymId::restDoubleWholeLegerLine : SymId::restDoubleWhole;
260 : }
261 : // fall through
262 : case DurationType::V_WHOLE:
263 55879 : return (line < 0 || line >= lines) ? SymId::restWholeLegerLine : SymId::restWhole;
264 2542 : case DurationType::V_HALF:
265 2542 : return (line < 0 || line >= lines) ? SymId::restHalfLegerLine : SymId::restHalf;
266 4293 : case DurationType::V_QUARTER:
267 4293 : return SymId::restQuarter;
268 3038 : case DurationType::V_EIGHTH:
269 3038 : return SymId::rest8th;
270 934 : case DurationType::V_16TH:
271 934 : return SymId::rest16th;
272 154 : case DurationType::V_32ND:
273 154 : return SymId::rest32nd;
274 44 : case DurationType::V_64TH:
275 44 : return SymId::rest64th;
276 9 : case DurationType::V_128TH:
277 9 : return SymId::rest128th;
278 2 : case DurationType::V_256TH:
279 2 : return SymId::rest256th;
280 0 : case DurationType::V_512TH:
281 0 : return SymId::rest512th;
282 0 : case DurationType::V_1024TH:
283 0 : return SymId::rest1024th;
284 0 : default:
285 0 : LOGD("unknown rest type %d", int(type));
286 0 : return SymId::restQuarter;
287 : }
288 : }
289 :
290 133216 : double Rest::symWidthNoLedgerLines(LayoutData* ldata) const
291 : {
292 133216 : if (ldata->sym == SymId::restHalfLegerLine) {
293 22 : return symWidth(SymId::restHalf);
294 : }
295 133194 : if (ldata->sym == SymId::restWholeLegerLine) {
296 0 : return symWidth(SymId::restWhole);
297 : }
298 133194 : if (ldata->sym == SymId::restDoubleWholeLegerLine) {
299 0 : return symWidth(SymId::restDoubleWhole);
300 : }
301 133194 : return symWidth(ldata->sym);
302 : }
303 :
304 : //---------------------------------------------------------
305 : // checkDots
306 : //---------------------------------------------------------
307 :
308 66716 : void Rest::checkDots()
309 : {
310 66716 : int n = dots() - int(m_dots.size());
311 66858 : for (int i = 0; i < n; ++i) {
312 142 : NoteDot* dot = Factory::createNoteDot(this);
313 142 : dot->setVisible(visible());
314 142 : score()->undoAddElement(dot);
315 : }
316 66716 : if (n < 0) {
317 4 : for (int i = 0; i < -n; ++i) {
318 2 : score()->undoRemoveElement(m_dots.back());
319 : }
320 : }
321 66716 : }
322 :
323 : //---------------------------------------------------------
324 : // dot
325 : //---------------------------------------------------------
326 :
327 108 : NoteDot* Rest::dot(int n)
328 : {
329 108 : checkDots();
330 108 : return m_dots[n];
331 : }
332 :
333 379545 : const std::vector<NoteDot*>& Rest::dotList() const
334 : {
335 379545 : return m_dots;
336 : }
337 :
338 : //---------------------------------------------------------
339 : // getDotline
340 : //---------------------------------------------------------
341 :
342 66608 : int Rest::getDotline(DurationType durationType)
343 : {
344 66608 : int dl = -1;
345 66608 : switch (durationType) {
346 198 : case DurationType::V_64TH:
347 : case DurationType::V_32ND:
348 198 : dl = -3;
349 198 : break;
350 11 : case DurationType::V_1024TH:
351 : case DurationType::V_512TH:
352 : case DurationType::V_256TH:
353 : case DurationType::V_128TH:
354 11 : dl = -5;
355 11 : break;
356 55812 : case DurationType::V_MEASURE:
357 : case DurationType::V_WHOLE:
358 55812 : dl = 1;
359 55812 : break;
360 10587 : default:
361 10587 : dl = -1;
362 10587 : break;
363 : }
364 66608 : return dl;
365 : }
366 :
367 69555 : bool Rest::isWholeRest() const
368 : {
369 69555 : TDuration durType = durationType();
370 69555 : return durType == DurationType::V_WHOLE
371 69555 : || (durType == DurationType::V_MEASURE && measure() && measure()->ticks() < Fraction(2, 1));
372 : }
373 :
374 10796 : bool Rest::isBreveRest() const
375 : {
376 10796 : TDuration durType = durationType();
377 10796 : return durType == DurationType::V_BREVE
378 10796 : || (durType == DurationType::V_MEASURE && measure() && measure()->ticks() >= Fraction(2, 1));
379 : }
380 :
381 : //---------------------------------------------------------
382 : // upPos
383 : //---------------------------------------------------------
384 :
385 0 : double Rest::upPos() const
386 : {
387 0 : return symBbox(ldata()->sym()).y();
388 : }
389 :
390 : //---------------------------------------------------------
391 : // downPos
392 : //---------------------------------------------------------
393 :
394 0 : double Rest::downPos() const
395 : {
396 0 : return symBbox(ldata()->sym()).y() + symHeight(ldata()->sym());
397 : }
398 :
399 : //---------------------------------------------------------
400 : // scanElements
401 : //---------------------------------------------------------
402 :
403 6599 : void Rest::scanElements(std::function<void(EngravingItem*)> func)
404 : {
405 6599 : ChordRest::scanElements(func);
406 6599 : for (EngravingItem* e : el()) {
407 0 : e->scanElements(func);
408 : }
409 6605 : for (NoteDot* dot : m_dots) {
410 6 : dot->scanElements(func);
411 : }
412 6599 : if (!isGap() || debugDrawGap()) {
413 6574 : func(this);
414 : }
415 6599 : if (leftParen()) {
416 0 : func(leftParen());
417 : }
418 6599 : if (rightParen()) {
419 0 : func(rightParen());
420 : }
421 6599 : }
422 :
423 : //---------------------------------------------------------
424 : // setTrack
425 : //---------------------------------------------------------
426 :
427 27636 : void Rest::setTrack(track_idx_t val)
428 : {
429 27636 : ChordRest::setTrack(val);
430 27639 : for (NoteDot* dot : m_dots) {
431 3 : dot->setTrack(val);
432 : }
433 27636 : }
434 :
435 : //---------------------------------------------------------
436 : // mag
437 : //---------------------------------------------------------
438 :
439 1220773 : double Rest::mag() const
440 : {
441 1220773 : double m = staff() ? staff()->staffMag(this) : 1.0;
442 1220773 : return m * intrinsicMag();
443 : }
444 :
445 : //---------------------------------------------------------
446 : // intrinsicMag
447 : // returns the INTRINSIC mag of the rest (i.e. NOT scaled
448 : // by staff size)
449 : //---------------------------------------------------------
450 :
451 1221644 : double Rest::intrinsicMag() const
452 : {
453 1221644 : double m = 1.0;
454 1221644 : if (isSmall()) {
455 650 : m *= style().styleD(Sid::smallNoteMag);
456 : }
457 1221644 : return m;
458 : }
459 :
460 : //---------------------------------------------------------
461 : // rightEdge
462 : //---------------------------------------------------------
463 :
464 0 : double Rest::rightEdge() const
465 : {
466 0 : return x() + width();
467 : }
468 :
469 56 : double Rest::centerX() const
470 : {
471 56 : SymId sym = ldata()->sym();
472 56 : RectF bbox = symBbox(sym);
473 112 : return bbox.left() + bbox.width() / 2;
474 : }
475 :
476 : //---------------------------------------------------------
477 : // accent
478 : //---------------------------------------------------------
479 :
480 2 : bool Rest::accent()
481 : {
482 2 : return voice() >= 2 && isSmall();
483 : }
484 :
485 : //---------------------------------------------------------
486 : // setAccent
487 : //---------------------------------------------------------
488 :
489 2 : void Rest::setAccent(bool flag)
490 : {
491 2 : undoChangeProperty(Pid::SMALL, flag);
492 2 : if (voice() % 2 == 0) {
493 2 : if (flag) {
494 2 : double yOffset = -(ldata()->bbox().bottom());
495 2 : if (durationType() >= DurationType::V_HALF) {
496 0 : yOffset -= staff()->spatium(tick()) * 0.5;
497 : }
498 2 : mutldata()->moveY(yOffset);
499 : }
500 : }
501 2 : }
502 :
503 : //---------------------------------------------------------
504 : // accessibleInfo
505 : //---------------------------------------------------------
506 :
507 0 : String Rest::accessibleInfo() const
508 : {
509 0 : String voice = muse::mtrc("engraving", "Voice: %1").arg(track() % VOICES + 1);
510 0 : return muse::mtrc("engraving", "%1; Duration: %2; %3").arg(EngravingItem::accessibleInfo(), durationUserName(), voice);
511 0 : }
512 :
513 : //---------------------------------------------------------
514 : // screenReaderInfo
515 : //---------------------------------------------------------
516 :
517 0 : String Rest::screenReaderInfo() const
518 : {
519 0 : Measure* m = measure();
520 0 : bool voices = m ? m->hasVoices(staffIdx()) : false;
521 0 : String voice = voices ? (u"; " + muse::mtrc("engraving", "Voice: %1").arg(track() % VOICES + 1)) : u"";
522 0 : String crossStaff;
523 0 : if (staffMove() < 0) {
524 0 : crossStaff = u"; " + muse::mtrc("engraving", "Cross-staff above");
525 0 : } else if (staffMove() > 0) {
526 0 : crossStaff = u"; " + muse::mtrc("engraving", "Cross-staff below");
527 : }
528 0 : return String(u"%1 %2%3%4").arg(EngravingItem::accessibleInfo(), durationUserName(), crossStaff, voice);
529 0 : }
530 :
531 : //---------------------------------------------------------
532 : // add
533 : //---------------------------------------------------------
534 :
535 154 : void Rest::add(EngravingItem* e)
536 : {
537 154 : if (e->ownershipParent() != this) {
538 9 : e->setOwnershipParent(this);
539 : }
540 154 : e->setTrack(track());
541 :
542 154 : switch (e->type()) {
543 148 : case ElementType::NOTEDOT:
544 148 : m_dots.push_back(toNoteDot(e));
545 148 : e->added();
546 148 : break;
547 0 : case ElementType::DEAD_SLAPPED:
548 0 : m_deadSlapped = toDeadSlapped(e);
549 0 : e->added();
550 0 : break;
551 6 : default:
552 6 : ChordRest::add(e);
553 6 : break;
554 : }
555 154 : }
556 :
557 : //---------------------------------------------------------
558 : // remove
559 : //---------------------------------------------------------
560 :
561 9 : void Rest::remove(EngravingItem* e)
562 : {
563 9 : switch (e->type()) {
564 9 : case ElementType::NOTEDOT:
565 9 : m_dots.pop_back();
566 9 : e->removed();
567 9 : break;
568 0 : case ElementType::DEAD_SLAPPED:
569 0 : m_deadSlapped = nullptr;
570 : // fallthrough
571 0 : case ElementType::SYMBOL:
572 : case ElementType::IMAGE:
573 0 : if (!removeEl(e)) {
574 0 : LOGD("Rest::remove(): cannot find %s", e->typeName());
575 : } else {
576 0 : e->removed();
577 : }
578 0 : break;
579 0 : default:
580 0 : ChordRest::remove(e);
581 0 : break;
582 : }
583 9 : }
584 :
585 : //---------------------------------------------------------
586 : // localSpatiumChanged
587 : //---------------------------------------------------------
588 :
589 0 : void Rest::localSpatiumChanged(double oldValue, double newValue)
590 : {
591 0 : ChordRest::localSpatiumChanged(oldValue, newValue);
592 0 : for (EngravingItem* e : m_dots) {
593 0 : e->localSpatiumChanged(oldValue, newValue);
594 : }
595 0 : for (EngravingItem* e : el()) {
596 0 : e->localSpatiumChanged(oldValue, newValue);
597 : }
598 0 : }
599 :
600 : //---------------------------------------------------------
601 : // propertyDefault
602 : //---------------------------------------------------------
603 :
604 175457 : PropertyValue Rest::propertyDefault(Pid propertyId) const
605 : {
606 175457 : switch (propertyId) {
607 0 : case Pid::GAP:
608 0 : return false;
609 14483 : case Pid::ALIGN_WITH_OTHER_RESTS:
610 14483 : return true;
611 160974 : default:
612 160974 : return ChordRest::propertyDefault(propertyId);
613 : }
614 : }
615 :
616 : //---------------------------------------------------------
617 : // resetProperty
618 : //---------------------------------------------------------
619 :
620 0 : void Rest::resetProperty(Pid id)
621 : {
622 0 : setProperty(id, propertyDefault(id));
623 0 : return;
624 : }
625 :
626 : //---------------------------------------------------------
627 : // getProperty
628 : //---------------------------------------------------------
629 :
630 176005 : PropertyValue Rest::getProperty(Pid propertyId) const
631 : {
632 176005 : switch (propertyId) {
633 24 : case Pid::GAP:
634 24 : return m_gap;
635 14483 : case Pid::ALIGN_WITH_OTHER_RESTS:
636 14483 : return alignWithOtherRests();
637 161498 : default:
638 161498 : return ChordRest::getProperty(propertyId);
639 : }
640 : }
641 :
642 : //---------------------------------------------------------
643 : // setProperty
644 : //---------------------------------------------------------
645 :
646 295 : bool Rest::setProperty(Pid propertyId, const PropertyValue& v)
647 : {
648 295 : switch (propertyId) {
649 7 : case Pid::GAP:
650 7 : m_gap = v.toBool();
651 7 : break;
652 8 : case Pid::VISIBLE:
653 8 : setVisible(v.toBool());
654 8 : break;
655 82 : case Pid::OFFSET:
656 82 : setOffset(v.value<PointF>());
657 82 : if (measure() && durationType().type() == DurationType::V_MEASURE) {
658 72 : measure()->triggerLayout();
659 : }
660 82 : break;
661 0 : case Pid::ALIGN_WITH_OTHER_RESTS:
662 0 : setAlignWithOtherRests(v.toBool());
663 0 : break;
664 198 : default:
665 198 : return ChordRest::setProperty(propertyId, v);
666 : }
667 97 : triggerLayout();
668 97 : return true;
669 : }
670 :
671 : //---------------------------------------------------------
672 : // undoChangeDotsVisible
673 : //---------------------------------------------------------
674 :
675 0 : void Rest::undoChangeDotsVisible(bool v)
676 : {
677 0 : for (NoteDot* dot : m_dots) {
678 0 : dot->undoChangeProperty(Pid::VISIBLE, v);
679 : }
680 0 : }
681 :
682 : //---------------------------------------------------------
683 : // nextElement
684 : //---------------------------------------------------------
685 :
686 0 : EngravingItem* Rest::nextElement()
687 : {
688 0 : return ChordRest::nextElement();
689 : }
690 :
691 : //---------------------------------------------------------
692 : // prevElement
693 : //---------------------------------------------------------
694 :
695 0 : EngravingItem* Rest::prevElement()
696 : {
697 0 : return ChordRest::prevElement();
698 : }
699 :
700 : //---------------------------------------------------------
701 : // Rest::shouldNotBeDrawn
702 : // in tab staff, do not draw rests (except mmrests)
703 : // if rests are off OR if dur. symbols are on
704 : // also measures covered by MeasureRepeat show no rests
705 : //---------------------------------------------------------
706 :
707 369975 : bool Rest::shouldNotBeDrawn() const
708 : {
709 369975 : const StaffType* st = staff() ? staff()->staffTypeForElement(this) : nullptr;
710 369975 : if (generated()) {
711 0 : return true;
712 : }
713 :
714 369975 : if (st && st->isTabStaff() && (!st->showRests() || st->genDurations())
715 739950 : && (!measure() || !measure()->isMMRest())) {
716 5512 : return true;
717 : }
718 :
719 364463 : if (measure() && measure()->measureRepeatCount(staffIdx())) {
720 1400 : return true;
721 : }
722 :
723 363063 : return false;
724 : }
725 :
726 944 : bool Rest::debugDrawGap() const
727 : {
728 944 : return configuration()->debuggingOptions().showGapRests;
729 : }
730 :
731 : //---------------------------------------------------------
732 : // getPropertyStyle
733 : //---------------------------------------------------------
734 14776 : Sid Rest::getPropertyStyle(Pid pid) const
735 : {
736 14776 : return ChordRest::getPropertyStyle(pid);
737 : }
738 : }
|