LCOV - code coverage report
Current view: top level - src/engraving/rendering/score - layoutcontext.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 51.6 % 318 164
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 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              : }
        

Generated by: LCOV version 2.0-1