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) 2023 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 : #include "layoutcontext.h"
23 :
24 : #include "editing/addremoveelement.h"
25 : #include "editing/editpagelocks.h"
26 : #include "editing/editsystemlocks.h"
27 : #include "editing/mscoreview.h"
28 : #include "editing/transaction/transaction.h"
29 : #include "style/defaultstyle.h"
30 :
31 : #include "dom/score.h"
32 : #include "dom/spanner.h"
33 :
34 : #include "tlayout.h"
35 :
36 : using namespace mu::engraving;
37 : using namespace mu::engraving::rendering::score;
38 :
39 : // ================================================
40 : // LayoutConfiguration
41 : // ================================================
42 :
43 544749 : LayoutConfiguration::LayoutConfiguration(IGetScoreInternal* s)
44 544749 : : m_getScore(s)
45 544749 : {}
46 :
47 7679116 : const Score* LayoutConfiguration::score() const
48 : {
49 7679116 : const Score* score = m_getScore->score();
50 7679116 : IF_ASSERT_FAILED(score) {
51 0 : return nullptr;
52 : }
53 7679116 : return score;
54 : }
55 :
56 362661 : const LayoutOptions& LayoutConfiguration::options() const
57 : {
58 362661 : return score()->layoutOptions();
59 : }
60 :
61 0 : bool LayoutConfiguration::isPaletteMode() const
62 : {
63 0 : IF_ASSERT_FAILED(score()) {
64 0 : return false;
65 : }
66 :
67 0 : return score()->isPaletteScore();
68 : }
69 :
70 43 : bool LayoutConfiguration::isPrintingMode() const
71 : {
72 43 : IF_ASSERT_FAILED(score()) {
73 0 : return false;
74 : }
75 :
76 43 : return score()->printing();
77 : }
78 :
79 729 : std::shared_ptr<const IEngravingFont> LayoutConfiguration::engravingFont() const
80 : {
81 729 : IF_ASSERT_FAILED(score()) {
82 0 : return nullptr;
83 : }
84 729 : return score()->engravingFont();
85 : }
86 :
87 3650113 : const MStyle& LayoutConfiguration::style() const
88 : {
89 3650113 : IF_ASSERT_FAILED(score()) {
90 0 : return DefaultStyle::defaultStyle();
91 : }
92 3650113 : return score()->style();
93 : }
94 :
95 0 : bool LayoutConfiguration::isShowInvisible() const
96 : {
97 0 : IF_ASSERT_FAILED(score()) {
98 0 : return false;
99 : }
100 0 : return score()->isShowInvisible();
101 : }
102 :
103 161 : int LayoutConfiguration::pageNumberOffset() const
104 : {
105 161 : IF_ASSERT_FAILED(score()) {
106 0 : return 0;
107 : }
108 161 : return score()->pageNumberOffset();
109 : }
110 :
111 24069 : bool LayoutConfiguration::isVerticalSpreadEnabled() const
112 : {
113 24069 : return styleB(Sid::enableVerticalSpread) && (viewMode() != LayoutMode::SYSTEM);
114 : }
115 :
116 356 : double LayoutConfiguration::maxSystemDistance() const
117 : {
118 356 : if (isVerticalSpreadEnabled()) {
119 0 : return style().styleAbsolute(Sid::maxSystemSpread);
120 : } else {
121 356 : return style().styleAbsolute(Sid::maxSystemDistance);
122 : }
123 : }
124 :
125 14363 : bool LayoutConfiguration::isShowInstrumentNames() const
126 : {
127 14363 : return score()->showInstrumentNames();
128 : }
129 :
130 : // ================================================
131 : // DomAccessor
132 : // ================================================
133 :
134 544749 : DomAccessor::DomAccessor(IGetScoreInternal* s)
135 544749 : : m_getScore(s)
136 544749 : {}
137 :
138 14482697 : const Score* DomAccessor::score() const
139 : {
140 14482697 : return m_getScore->score();
141 : }
142 :
143 126605 : Score* DomAccessor::score()
144 : {
145 126605 : return m_getScore->score();
146 : }
147 :
148 86180 : const std::vector<Part*>& DomAccessor::parts() const
149 : {
150 86180 : IF_ASSERT_FAILED(score()) {
151 0 : static const std::vector<Part*> dummy;
152 0 : return dummy;
153 : }
154 86180 : return score()->parts();
155 : }
156 :
157 38123 : size_t DomAccessor::visiblePartCount() const
158 : {
159 38123 : IF_ASSERT_FAILED(score()) {
160 0 : return 0;
161 : }
162 38123 : return score()->visiblePartCount();
163 : }
164 :
165 23794 : std::vector<Part*> DomAccessor::visibleParts() const
166 : {
167 23794 : IF_ASSERT_FAILED(score()) {
168 0 : return {};
169 : }
170 23794 : return score()->visibleParts();
171 : }
172 :
173 752 : size_t DomAccessor::npages() const
174 : {
175 752 : IF_ASSERT_FAILED(score()) {
176 0 : return 0;
177 : }
178 752 : return score()->npages();
179 : }
180 :
181 4 : const std::vector<Page*>& DomAccessor::pages() const
182 : {
183 4 : IF_ASSERT_FAILED(score()) {
184 0 : static const std::vector<Page*> dummy;
185 0 : return dummy;
186 : }
187 4 : return score()->pages();
188 : }
189 :
190 4322 : std::vector<Page*>& DomAccessor::pages()
191 : {
192 4322 : IF_ASSERT_FAILED(score()) {
193 0 : static std::vector<Page*> dummy;
194 0 : return dummy;
195 : }
196 4322 : return score()->pages();
197 : }
198 :
199 15686 : const std::vector<System*>& DomAccessor::systems() const
200 : {
201 15686 : IF_ASSERT_FAILED(score()) {
202 0 : static const std::vector<System*> dummy;
203 0 : return dummy;
204 : }
205 15686 : return score()->systems();
206 : }
207 :
208 10063 : std::vector<System*>& DomAccessor::systems()
209 : {
210 10063 : IF_ASSERT_FAILED(score()) {
211 0 : static std::vector<System*> dummy;
212 0 : return dummy;
213 : }
214 10063 : return score()->systems();
215 : }
216 :
217 1556454 : size_t DomAccessor::nstaves() const
218 : {
219 1556454 : IF_ASSERT_FAILED(score()) {
220 0 : return 0;
221 : }
222 1556454 : return score()->nstaves();
223 : }
224 :
225 0 : size_t DomAccessor::visibleStaffCount() const
226 : {
227 0 : IF_ASSERT_FAILED(score()) {
228 0 : return 0;
229 : }
230 :
231 0 : return score()->visibleStavesCount();
232 : }
233 :
234 22827 : const std::vector<Staff*>& DomAccessor::staves() const
235 : {
236 22827 : IF_ASSERT_FAILED(score()) {
237 0 : static const std::vector<Staff*> dummy;
238 0 : return dummy;
239 : }
240 22827 : return score()->staves();
241 : }
242 :
243 1698219 : const Staff* DomAccessor::staff(staff_idx_t idx) const
244 : {
245 1698219 : IF_ASSERT_FAILED(score()) {
246 0 : return nullptr;
247 : }
248 1698219 : return score()->staff(idx);
249 : }
250 :
251 37628 : bool DomAccessor::allStavesInvisible() const
252 : {
253 37628 : IF_ASSERT_FAILED(score()) {
254 0 : return false;
255 : }
256 37628 : return score()->allStavesInvisible();
257 : }
258 :
259 3516601 : size_t DomAccessor::ntracks() const
260 : {
261 3516601 : IF_ASSERT_FAILED(score()) {
262 0 : return 0;
263 : }
264 3516601 : return score()->ntracks();
265 : }
266 :
267 0 : size_t DomAccessor::nmeasures() const
268 : {
269 0 : IF_ASSERT_FAILED(score()) {
270 0 : return 0;
271 : }
272 0 : return score()->nmeasures();
273 : }
274 :
275 129 : const Measure* DomAccessor::tick2measure(const Fraction& tick) const
276 : {
277 129 : IF_ASSERT_FAILED(score()) {
278 0 : return nullptr;
279 : }
280 129 : return score()->tick2measure(tick);
281 : }
282 :
283 48396 : const Measure* DomAccessor::tick2measureMM(const Fraction& tick) const
284 : {
285 48396 : IF_ASSERT_FAILED(score()) {
286 0 : return nullptr;
287 : }
288 48396 : return score()->tick2measureMM(tick);
289 : }
290 :
291 23428 : const Measure* DomAccessor::firstMeasure() const
292 : {
293 23428 : IF_ASSERT_FAILED(score()) {
294 0 : return nullptr;
295 : }
296 23428 : return score()->firstMeasure();
297 : }
298 :
299 0 : Measure* DomAccessor::firstMeasure()
300 : {
301 0 : IF_ASSERT_FAILED(score()) {
302 0 : return nullptr;
303 : }
304 0 : return score()->firstMeasure();
305 : }
306 :
307 10 : const Measure* DomAccessor::lastMeasure() const
308 : {
309 10 : IF_ASSERT_FAILED(score()) {
310 0 : return nullptr;
311 : }
312 10 : return score()->lastMeasure();
313 : }
314 :
315 46465 : const Measure* DomAccessor::lastMeasureMM() const
316 : {
317 46465 : IF_ASSERT_FAILED(score()) {
318 0 : return nullptr;
319 : }
320 46465 : return score()->lastMeasureMM();
321 : }
322 :
323 0 : Measure* DomAccessor::lastMeasure()
324 : {
325 0 : IF_ASSERT_FAILED(score()) {
326 0 : return nullptr;
327 : }
328 0 : return score()->lastMeasure();
329 : }
330 :
331 0 : Measure* DomAccessor::lastMeasureMM()
332 : {
333 0 : IF_ASSERT_FAILED(score()) {
334 0 : return nullptr;
335 : }
336 0 : return score()->lastMeasureMM();
337 : }
338 :
339 11376 : Measure* DomAccessor::tick2measure(const Fraction& tick)
340 : {
341 11376 : IF_ASSERT_FAILED(score()) {
342 0 : return nullptr;
343 : }
344 11376 : return score()->tick2measure(tick);
345 : }
346 :
347 0 : Measure* DomAccessor::tick2measureMM(const Fraction& tick)
348 : {
349 0 : IF_ASSERT_FAILED(score()) {
350 0 : return nullptr;
351 : }
352 0 : return score()->tick2measureMM(tick);
353 : }
354 :
355 61365 : const SpannerMap& DomAccessor::spannerMap() const
356 : {
357 61365 : IF_ASSERT_FAILED(score()) {
358 0 : static const SpannerMap dummy;
359 0 : return dummy;
360 : }
361 61365 : return score()->spannerMap();
362 : }
363 :
364 20106 : const Segment* DomAccessor::lastSegment() const
365 : {
366 20106 : IF_ASSERT_FAILED(score()) {
367 0 : return nullptr;
368 : }
369 20106 : return score()->lastSegment();
370 : }
371 :
372 0 : const ChordRest* DomAccessor::findCR(Fraction tick, track_idx_t track) const
373 : {
374 0 : IF_ASSERT_FAILED(score()) {
375 0 : return nullptr;
376 : }
377 0 : return score()->findCR(tick, track);
378 : }
379 :
380 9473 : const RangeLocks* DomAccessor::systemLocks() const
381 : {
382 9473 : IF_ASSERT_FAILED(score()) {
383 0 : return nullptr;
384 : }
385 9473 : return score()->systemLocks();
386 : }
387 :
388 4125 : const RangeLocks* DomAccessor::pageLocks() const
389 : {
390 4125 : IF_ASSERT_FAILED(score()) {
391 0 : return nullptr;
392 : }
393 4125 : return score()->pageLocks();
394 : }
395 :
396 0 : const PaddingTable& DomAccessor::paddingTable() const
397 : {
398 0 : return score()->paddingTables().horizontalPaddingTable();
399 : }
400 :
401 32289 : const std::vector<BracketItem*>& DomAccessor::brackets(staff_idx_t staffIdx) const
402 : {
403 32289 : return score()->brackets(staffIdx);
404 : }
405 :
406 126 : ChordRest* DomAccessor::findCR(Fraction tick, track_idx_t track)
407 : {
408 126 : IF_ASSERT_FAILED(score()) {
409 0 : return nullptr;
410 : }
411 126 : return score()->findCR(tick, track);
412 : }
413 :
414 3822 : MeasureBase* DomAccessor::first()
415 : {
416 3822 : IF_ASSERT_FAILED(score()) {
417 0 : return nullptr;
418 : }
419 3822 : return score()->first();
420 : }
421 :
422 7636 : DummyParent* DomAccessor::dummyParent() const
423 : {
424 7636 : IF_ASSERT_FAILED(score()) {
425 0 : return nullptr;
426 : }
427 7636 : return score()->dummy();
428 : }
429 :
430 46 : void DomAccessor::doUndoAddElement(EngravingItem* item)
431 : {
432 46 : if (item->generated()) {
433 0 : addElement(item);
434 : } else {
435 46 : undo(new AddElement(item));
436 : }
437 46 : }
438 :
439 659 : void DomAccessor::undoAddElement(EngravingItem* item, bool addToLinkedStaves, bool ctrlModifier)
440 : {
441 659 : IF_ASSERT_FAILED(score()) {
442 0 : return;
443 : }
444 659 : score()->undoAddElement(item, addToLinkedStaves, ctrlModifier);
445 : }
446 :
447 0 : void DomAccessor::doUndoRemoveElement(EngravingItem* item)
448 : {
449 0 : if (item->generated()) {
450 0 : removeElement(item);
451 0 : item->deleteLater();
452 : } else {
453 0 : undo(new RemoveElement(item));
454 : }
455 0 : }
456 :
457 14 : void DomAccessor::undoRemoveElement(EngravingItem* item)
458 : {
459 14 : IF_ASSERT_FAILED(score()) {
460 0 : return;
461 : }
462 14 : score()->undoRemoveElement(item);
463 : }
464 :
465 415 : void DomAccessor::undo(UndoableCommand* cmd) const
466 : {
467 415 : IF_ASSERT_FAILED(score()) {
468 0 : return;
469 : }
470 415 : score()->undo(cmd);
471 : }
472 :
473 25653 : void DomAccessor::addElement(EngravingItem* item)
474 : {
475 25653 : IF_ASSERT_FAILED(score()) {
476 0 : return;
477 : }
478 25653 : score()->addElement(item);
479 : }
480 :
481 0 : void DomAccessor::removeElement(EngravingItem* item)
482 : {
483 0 : IF_ASSERT_FAILED(score()) {
484 0 : return;
485 : }
486 0 : score()->removeElement(item);
487 : }
488 :
489 166 : void DomAccessor::updateLocksOnCreateMMRest(Measure* first, Measure* last)
490 : {
491 166 : IF_ASSERT_FAILED(score()) {
492 0 : return;
493 : }
494 166 : Transaction& tx = score()->transactionManager()->currentOrDummyTransaction();
495 166 : EditPageLocks::updatePageLocksOnCreateMMRests(tx, score(), first, last);
496 166 : EditSystemLocks::updateSystemLocksOnCreateMMRests(tx, score(), first, last);
497 : }
498 :
499 151 : void DomAccessor::undoChangeParent(EngravingItem* element, EngravingItem* parent, staff_idx_t staff, bool changeLinksParents)
500 : {
501 151 : IF_ASSERT_FAILED(score()) {
502 0 : return;
503 : }
504 151 : score()->undoChangeParent(element, parent, staff, changeLinksParents);
505 : }
506 :
507 243 : void DomAccessor::addUnmanagedSpanner(Spanner* s)
508 : {
509 243 : IF_ASSERT_FAILED(score()) {
510 0 : return;
511 : }
512 243 : score()->addUnmanagedSpanner(s);
513 : }
514 :
515 7388 : const std::set<Spanner*>& DomAccessor::unmanagedSpanners() const
516 : {
517 7388 : IF_ASSERT_FAILED(score()) {
518 0 : static const std::set<Spanner*> dummy;
519 0 : return dummy;
520 : }
521 7388 : return score()->unmanagedSpanners();
522 : }
523 :
524 : // =============================================================
525 : // LayoutDebug
526 : // =============================================================
527 0 : LayoutDebug* LayoutDebug::instance()
528 : {
529 0 : static LayoutDebug ld;
530 0 : return &ld;
531 : }
532 :
533 0 : void LayoutDebug::callClear()
534 : {
535 0 : m_currentCall = nullptr;
536 0 : m_calls.clear();
537 0 : }
538 :
539 0 : void LayoutDebug::callBegin(const std::string_view& name, const std::string_view& info)
540 : {
541 : //LOGDA() << name << " " << info;
542 0 : Call c;
543 0 : c.name = name;
544 0 : c.info = info;
545 0 : if (m_currentCall) {
546 0 : c.top = m_currentCall;
547 0 : m_currentCall->nested.push_back(c);
548 0 : m_currentCall = &m_currentCall->nested.back();
549 : } else {
550 0 : m_calls.push_back(c);
551 0 : m_currentCall = &m_calls.back();
552 : }
553 0 : }
554 :
555 0 : void LayoutDebug::callEnd()
556 : {
557 0 : IF_ASSERT_FAILED(m_currentCall) {
558 0 : return;
559 : }
560 :
561 : //LOGDA() << m_currentCall->name << " " << m_currentCall->info;
562 0 : m_currentCall = m_currentCall->top;
563 : }
564 :
565 0 : void LayoutDebug::callDump(const LayoutDebug::Call& c, std::stringstream& ss, int& indent)
566 : {
567 0 : std::string gap;
568 0 : gap.resize(indent * 2, ' ');
569 0 : ss << "\n";
570 0 : ss << gap << c.name << " " << c.info;
571 :
572 0 : for (const Call& cn : c.nested) {
573 0 : ++indent;
574 0 : callDump(cn, ss, indent);
575 0 : --indent;
576 : }
577 0 : }
578 :
579 0 : void LayoutDebug::callDump(std::stringstream& ss) const
580 : {
581 0 : for (const Call& c : m_calls) {
582 0 : int indent = 0;
583 0 : callDump(c, ss, indent);
584 : }
585 0 : }
586 :
587 0 : void LayoutDebug::callPrint()
588 : {
589 0 : LOGDA() << "\n" << callDump();
590 0 : }
591 :
592 : // =============================================================
593 : // LayoutContext
594 : // =============================================================
595 :
596 544749 : LayoutContext::LayoutContext(Score* score)
597 544749 : : m_score(score), m_configuration(this), m_dom(this)
598 : {
599 544749 : if (score) {
600 544749 : m_state.setFirstSystemIndent(score->style().styleB(Sid::enableIndentationOnFirstSystem));
601 : }
602 544749 : }
603 :
604 544749 : LayoutContext::~LayoutContext()
605 : {
606 544749 : for (MuseScoreView* v : m_score->getViewer()) {
607 0 : v->layoutChanged();
608 : }
609 544749 : }
610 :
611 0 : bool LayoutContext::isValid() const
612 : {
613 0 : return m_score != nullptr;
614 : }
615 :
616 119986 : IEngravingFontPtr LayoutContext::engravingFont() const
617 : {
618 119986 : IF_ASSERT_FAILED(m_score) {
619 0 : return nullptr;
620 : }
621 119986 : return m_score->engravingFont();
622 : }
623 :
624 6811530 : const DomAccessor& LayoutContext::dom() const
625 : {
626 6811530 : return m_dom;
627 : }
628 :
629 68690 : DomAccessor& LayoutContext::mutDom()
630 : {
631 68690 : return m_dom;
632 : }
633 :
634 926292 : const LayoutState& LayoutContext::state() const
635 : {
636 926292 : return m_state;
637 : }
638 :
639 573777 : LayoutState& LayoutContext::mutState()
640 : {
641 573777 : return m_state;
642 : }
643 :
644 0 : const Selection& LayoutContext::selection() const
645 : {
646 0 : IF_ASSERT_FAILED(m_score) {
647 0 : static const Selection dummy;
648 0 : return dummy;
649 : }
650 0 : return m_score->selection();
651 : }
652 :
653 0 : void LayoutContext::select(EngravingItem* item, SelectType type, staff_idx_t staff)
654 : {
655 0 : IF_ASSERT_FAILED(m_score) {
656 0 : return;
657 : }
658 0 : m_score->select(item, type, staff);
659 : }
660 :
661 0 : void LayoutContext::deselect(EngravingItem* el)
662 : {
663 0 : IF_ASSERT_FAILED(m_score) {
664 0 : return;
665 : }
666 0 : m_score->deselect(el);
667 : }
|