LCOV - code coverage report
Current view: top level - src/engraving/rendering/score - layoutcontext.h Coverage Total Hit
Test: filtered_coverage.info Lines: 93.8 % 80 75
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              : 
      23              : #pragma once
      24              : 
      25              : #include <vector>
      26              : #include <set>
      27              : #include <unordered_set>
      28              : 
      29              : #include "../../types/fraction.h"
      30              : #include "../../types/types.h"
      31              : 
      32              : #include "../../style/style.h"
      33              : #include "../../iengravingfont.h"
      34              : #include "../../dom/mscore.h"
      35              : 
      36              : #include "../layoutoptions.h"
      37              : 
      38              : #ifdef MUE_ENABLE_ENGRAVING_RENDER_DEBUG
      39              : #include "log.h"
      40              : #include "logstream.h"
      41              : #define LAYOUT_CALL_CLEAR mu::engraving::rendering::dev::LayoutDebug::instance()->callClear
      42              : #define LAYOUT_CALL_BEGIN(name) mu::engraving::rendering::dev::LayoutDebug::CallBegin(name)
      43              : #define LAYOUT_CALL_END mu::engraving::rendering::dev::LayoutDebug::instance()->callEnd
      44              : #define LAYOUT_CALL() mu::engraving::rendering::dev::LayoutDebug::CallMarker _ldcall; _ldcall.begin(FUNCNAME).stream
      45              : #define LAYOUT_ITEM_INFO(item) item->typeName() << "(" << item->eid() << ")"
      46              : 
      47              : #define LAYOUT_CALL_PRINT mu::engraving::rendering::dev::LayoutDebug::instance()->callPrint
      48              : #else
      49              : #define LAYOUT_CALL_CLEAR()
      50              : #define LAYOUT_CALL_BEGIN(name, info)
      51              : #define LAYOUT_CALL_END()
      52              : #define LAYOUT_CALL() if (0) muse::logger::Stream()
      53              : #define LAYOUT_ITEM_INFO(item) ""
      54              : #define LAYOUT_CALL_PRINT()
      55              : #endif
      56              : 
      57              : namespace mu::engraving {
      58              : class DummyParent;
      59              : class EngravingItem;
      60              : class MeasureBase;
      61              : class Part;
      62              : class Page;
      63              : class Score;
      64              : class Spanner;
      65              : class SpannerMap;
      66              : class System;
      67              : class RangeLocks;
      68              : class Staff;
      69              : class Measure;
      70              : class ChordRest;
      71              : class Segment;
      72              : class BracketItem;
      73              : struct PaddingTable;
      74              : 
      75              : class UndoableCommand;
      76              : class EditData;
      77              : 
      78              : class Selection;
      79              : }
      80              : 
      81              : namespace mu::engraving::rendering::score {
      82              : class IGetScoreInternal
      83              : {
      84              : private:
      85              :     friend class LayoutConfiguration;
      86              :     friend class DomAccessor;
      87              : 
      88              :     virtual Score* score() = 0;
      89              : };
      90              : 
      91              : class LayoutConfiguration
      92              : {
      93              : public:
      94              :     LayoutConfiguration(IGetScoreInternal* s);
      95              : 
      96        76835 :     LayoutMode viewMode() const { return options().mode; }
      97        68421 :     bool isMode(LayoutMode m) const { return options().isMode(m); }
      98         3494 :     bool isLineMode() const { return isMode(LayoutMode::LINE); }
      99        80981 :     bool isLinearMode() const { return options().isLinearMode(); }
     100        38224 :     bool isFloatMode() const { return isMode(LayoutMode::FLOAT); }
     101              :     bool isPaletteMode() const;
     102              :     bool isPrintingMode() const;
     103              : 
     104        41575 :     bool isShowVBox() const { return options().isShowVBox; }
     105        94849 :     double noteHeadWidth() const { return options().noteHeadWidth; }
     106              :     bool isShowInvisible() const;
     107              :     int pageNumberOffset() const;
     108              :     bool isVerticalSpreadEnabled() const;
     109              :     double maxSystemDistance() const;
     110              :     bool isShowInstrumentNames() const;
     111              : 
     112              :     std::shared_ptr<const IEngravingFont> engravingFont() const;
     113              : 
     114              :     const MStyle& style() const;
     115              : 
     116       257015 :     const PropertyValue& styleV(Sid idx) const { return style().styleV(idx); }
     117       253625 :     Spatium styleS(Sid idx) const { return style().styleS(idx); }
     118       567573 :     double styleAbsolute(Sid idx) const { return style().styleAbsolute(idx); }
     119        24398 :     String styleSt(Sid idx) const { return style().styleSt(idx); }
     120      1194565 :     bool styleB(Sid idx) const { return style().styleB(idx); }
     121       355159 :     double styleD(Sid idx) const { return style().styleD(idx); }
     122       148693 :     int styleI(Sid idx) const { return style().styleI(idx); }
     123              : 
     124       121448 :     double spatium() const { return styleD(Sid::spatium); }
     125       113104 :     double defaultSpatium() const { return style().defaultSpatium(); }
     126         1994 :     double point(const Spatium sp) const { return sp.val() * spatium(); }
     127       113104 :     double magS(double mag) const { return mag * (spatium() / defaultSpatium()); }
     128              : 
     129         4161 :     double loWidth() const { return styleD(Sid::pageWidth) * DPI; }
     130         4161 :     double loHeight() const { return styleD(Sid::pageHeight) * DPI; }
     131              : 
     132           58 :     bool firstSystemIndent() const { return styleB(Sid::enableIndentationOnFirstSystem); }
     133              : 
     134              : private:
     135              :     const Score* score() const;
     136              :     const LayoutOptions& options() const;
     137              : 
     138              :     IGetScoreInternal* m_getScore = nullptr;
     139              : };
     140              : 
     141              : class DomAccessor
     142              : {
     143              : public:
     144              : 
     145              :     DomAccessor(IGetScoreInternal* s);
     146              : 
     147              :     // Const access
     148              :     const std::vector<Part*>& parts() const;
     149              :     size_t visiblePartCount() const;
     150              :     std::vector<Part*> visibleParts() const;
     151              : 
     152              :     size_t npages() const;
     153              :     const std::vector<Page*>& pages() const;
     154              : 
     155              :     const std::vector<System*>& systems() const;
     156              : 
     157              :     size_t nstaves() const;
     158              :     size_t visibleStaffCount() const;
     159              :     const std::vector<Staff*>& staves() const;
     160              :     const Staff* staff(staff_idx_t idx) const;
     161              :     bool allStavesInvisible() const;
     162              : 
     163              :     size_t ntracks() const;
     164              : 
     165              :     size_t nmeasures() const;
     166              : 
     167              :     const Measure* tick2measure(const Fraction& tick) const;
     168              :     const Measure* tick2measureMM(const Fraction& tick) const;
     169              :     const Measure* firstMeasure() const;
     170              :     const Measure* lastMeasure() const;
     171              :     const Measure* lastMeasureMM() const;
     172              : 
     173              :     const SpannerMap& spannerMap() const;
     174              : 
     175              :     const Segment* lastSegment() const;
     176              : 
     177              :     const ChordRest* findCR(Fraction tick, track_idx_t track) const;
     178              : 
     179              :     const RangeLocks* systemLocks() const;
     180              :     const RangeLocks* pageLocks() const;
     181              : 
     182              :     const PaddingTable& paddingTable() const;
     183              : 
     184              :     const std::vector<BracketItem*>& brackets(staff_idx_t staffIdx) const;
     185              : 
     186              :     // Mutable access
     187              :     std::vector<Page*>& pages();
     188              :     std::vector<System*>& systems();
     189              : 
     190              :     MeasureBase* first();
     191              :     Measure* firstMeasure();
     192              :     Measure* lastMeasure();
     193              :     Measure* lastMeasureMM();
     194              :     Measure* tick2measure(const Fraction& tick);
     195              :     Measure* tick2measureMM(const Fraction& tick);
     196              : 
     197              :     ChordRest* findCR(Fraction tick, track_idx_t track);
     198              : 
     199              :     // Create/Remove
     200              :     const Score* score() const;
     201              :     Score* score();
     202              :     DummyParent* dummyParent() const;
     203              :     void doUndoAddElement(EngravingItem*);
     204              :     void undoAddElement(EngravingItem* item, bool addToLinkedStaves = true, bool ctrlModifier = false);
     205              :     void doUndoRemoveElement(EngravingItem* item);
     206              :     void undoRemoveElement(EngravingItem* item);
     207              :     void undo(UndoableCommand* cmd) const;
     208              :     void addElement(EngravingItem* item);
     209              :     void removeElement(EngravingItem* item);
     210              :     void updateLocksOnCreateMMRest(Measure* first, Measure* last);
     211              :     void undoChangeParent(EngravingItem* element, EngravingItem* parent, staff_idx_t staff, bool changeLinksParents = true);
     212              : 
     213              :     void addUnmanagedSpanner(Spanner* s);
     214              :     const std::set<Spanner*>& unmanagedSpanners() const;
     215              : 
     216              : private:
     217              :     IGetScoreInternal* m_getScore = nullptr;
     218              : };
     219              : 
     220              : class LayoutState
     221              : {
     222              : public:
     223              : 
     224              :     // Const
     225        81252 :     bool firstSystem() const { return m_firstSystem; }
     226         7964 :     bool firstSystemIndent() const { return m_firstSystemIndent; }
     227        33001 :     bool startWithLongNames() const { return m_startWithLongNames; }
     228              : 
     229        71214 :     const Fraction& tick() const { return m_tick; }
     230         7816 :     const Fraction& startTick() const { return m_startTick; }
     231        10348 :     const Fraction& endTick() const { return m_endTick; }
     232        11892 :     bool isLayoutAll() const { return m_isLayoutAll; }
     233              : 
     234        10906 :     const Page* page() const { return m_page; }
     235        18128 :     page_idx_t pageIdx() const { return m_pageIdx; }
     236              : 
     237        10378 :     const std::vector<System*>& systemList() const { return m_systemList; }
     238        49243 :     const System* prevSystem() const { return m_prevSystem; }
     239        71123 :     const System* curSystem() const { return m_curSystem; }
     240              : 
     241       144663 :     const MeasureBase* prevMeasure() const { return m_prevMeasure; }
     242       294484 :     const MeasureBase* curMeasure() const { return m_curMeasure; }
     243        30555 :     const MeasureBase* nextMeasure() const { return m_nextMeasure; }
     244          332 :     const MeasureBase* systemOldMeasure() const { return m_systemOldMeasure; }
     245           16 :     const MeasureBase* pageOldMeasure() const { return m_pageOldMeasure; }
     246        71430 :     int measureNumber() const { return m_measureNumber; }
     247              : 
     248        17406 :     bool rangeDone() const { return m_rangeDone; }
     249              : 
     250         3964 :     const std::unordered_set<System*>& systemsNeedingCentering() const { return m_systemsNeedingCentering; }
     251              : 
     252         3964 :     bool mustRecomputeHeadersFooters() const { return m_mustRecomputeHeadersFooters; }
     253              : 
     254        24782 :     double totalBracketsWidth() const { return m_totalBracketsWidth; }
     255              : 
     256              :     // Mutable
     257         3332 :     void setFirstSystem(bool val) { m_firstSystem = val; }
     258       544807 :     void setFirstSystemIndent(bool val) { m_firstSystemIndent = val; }
     259         6199 :     void setStartWithLongNames(bool val) { m_startWithLongNames = val; }
     260              : 
     261        31102 :     void setTick(const Fraction& t) { m_tick = t; }
     262          591 :     void setStartTick(const Fraction& t) { m_startTick = t; }
     263         3964 :     void setEndTick(const Fraction& t) { m_endTick = t; }
     264         3964 :     void setIsLayoutAll(bool v) { m_isLayoutAll = v; }
     265              : 
     266        56487 :     Page* page() { return m_page; }
     267         4752 :     void setPage(Page* p) { m_page = p; }
     268         4752 :     void setPageIdx(page_idx_t idx) { m_pageIdx = idx; }
     269              : 
     270        17538 :     std::vector<System*>& systemList() { return m_systemList; }
     271          591 :     void setSystemList(const std::vector<System*>& l) { m_systemList = l; }
     272              :     System* prevSystem() { return m_prevSystem; }
     273        14214 :     void setPrevSystem(System* s) { m_prevSystem = s; }
     274        50779 :     System* curSystem() { return m_curSystem; }
     275        14608 :     void setCurSystem(System* s) { m_curSystem = s; }
     276              : 
     277        30366 :     MeasureBase* prevMeasure() { return m_prevMeasure; }
     278        40732 :     void setPrevMeasure(MeasureBase* m) { m_prevMeasure = m; }
     279       349934 :     MeasureBase* curMeasure() { return m_curMeasure; }
     280        36931 :     void setCurMeasure(MeasureBase* m) { m_curMeasure = m; }
     281        64781 :     MeasureBase* nextMeasure() { return m_nextMeasure; }
     282        40895 :     void setNextMeasure(MeasureBase* m) { m_nextMeasure = m; }
     283         9473 :     void setSystemOldMeasure(MeasureBase* m) { m_systemOldMeasure = m; }
     284         4321 :     void setPageOldMeasure(MeasureBase* m) { m_pageOldMeasure = m; }
     285        31956 :     void setMeasureNumber(int n) { m_measureNumber = n; }
     286              : 
     287          279 :     void setRangeDone(bool val) { m_rangeDone = val; }
     288              : 
     289         7396 :     void addSystemNeedingCentering(System* s) { m_systemsNeedingCentering.insert(s); }
     290        10195 :     void removeSystemNeedingCentering(System* s) { m_systemsNeedingCentering.erase(s); }
     291         3964 :     void clearSystemsNeedingCentering() { m_systemsNeedingCentering.clear(); }
     292              : 
     293           10 :     void setMustRecomputeHeadersFooters(bool val) { m_mustRecomputeHeadersFooters = val; }
     294              : 
     295         3960 :     void setTotalBracketsWidth(double val) { m_totalBracketsWidth = val; }
     296              : 
     297              : private:
     298              : 
     299              :     bool m_firstSystem = true;
     300              :     bool m_firstSystemIndent = true;
     301              :     bool m_startWithLongNames = true;
     302              : 
     303              :     Fraction m_tick{ 0, 1 };
     304              :     Fraction m_startTick;
     305              :     Fraction m_endTick;
     306              :     bool m_isLayoutAll = false;
     307              : 
     308              :     Page* m_page = nullptr;
     309              :     page_idx_t m_pageIdx = 0;               // index in Score->page()s
     310              : 
     311              :     std::vector<System*> m_systemList;      // reusable systems
     312              :     System* m_prevSystem = nullptr;         // used during page layout
     313              :     System* m_curSystem = nullptr;
     314              : 
     315              :     MeasureBase* m_prevMeasure = nullptr;
     316              :     MeasureBase* m_curMeasure = nullptr;
     317              :     MeasureBase* m_nextMeasure = nullptr;
     318              :     MeasureBase* m_systemOldMeasure = nullptr;
     319              :     MeasureBase* m_pageOldMeasure = nullptr;
     320              :     int m_measureNumber = 0;
     321              : 
     322              :     bool m_rangeDone = false;
     323              : 
     324              :     std::unordered_set<System*> m_systemsNeedingCentering; // systems which have been laid out and still need SystemLayout::centerElementsBetweenStaves
     325              : 
     326              :     bool m_mustRecomputeHeadersFooters = false; // we may need to re-compute headers/footers after laying out all pages if they contained a page count
     327              : 
     328              :     // cache
     329              :     double m_totalBracketsWidth = -1.0;
     330              : };
     331              : 
     332              : class LayoutDebug
     333              : {
     334              : public:
     335              : 
     336              :     static LayoutDebug* instance();
     337              : 
     338              :     struct CallBeginMarker {
     339              :         std::string_view name;
     340              :         muse::logger::Stream stream;
     341              :         CallBeginMarker(const std::string_view& n)
     342              :             : name(n)
     343              :         {
     344              :         }
     345              : 
     346              :         ~CallBeginMarker()
     347              :         {
     348              :             LayoutDebug::instance()->callBegin(name, stream.str());
     349              :         }
     350              :     };
     351              : 
     352              :     struct CallMarker {
     353              :         CallBeginMarker begin(const std::string_view& n) { return CallBeginMarker(n); }
     354              : 
     355              :         ~CallMarker()
     356              :         {
     357              :             LayoutDebug::instance()->callEnd();
     358              :         }
     359              :     };
     360              : 
     361              :     void callClear();
     362              :     void callBegin(const std::string_view& name, const std::string_view& info);
     363              :     void callEnd();
     364              : 
     365              :     void callDump(std::stringstream& ss) const;
     366            0 :     std::string callDump() const
     367              :     {
     368            0 :         std::stringstream ss;
     369            0 :         callDump(ss);
     370            0 :         return ss.str();
     371            0 :     }
     372              : 
     373              :     void callPrint();
     374              : 
     375              : private:
     376              : 
     377              :     struct Call {
     378              :         std::string name;
     379              :         std::string info;
     380              :         Call* top = nullptr;
     381              :         std::vector<Call> nested;
     382              :     };
     383              : 
     384              :     static void callDump(const LayoutDebug::Call& c, std::stringstream& ss, int& indent);
     385              : 
     386              :     Call* m_currentCall;
     387              :     std::vector<Call> m_calls;
     388              : };
     389              : 
     390              : class LayoutContext : public IGetScoreInternal
     391              : {
     392              : public:
     393              :     LayoutContext(Score* s);
     394              :     ~LayoutContext();
     395              : 
     396              :     LayoutContext(const LayoutContext&) = delete;
     397              :     LayoutContext& operator=(const LayoutContext&) = delete;
     398              : 
     399              :     bool isValid() const;
     400              : 
     401              :     // Conf
     402              :     IEngravingFontPtr engravingFont() const;
     403      4364401 :     const LayoutConfiguration& conf() const { return m_configuration; }
     404              : 
     405              :     // Dom access
     406              :     const DomAccessor& dom() const;
     407              :     DomAccessor& mutDom();
     408              : 
     409              :     // State
     410              :     const LayoutState& state() const;
     411              :     LayoutState& mutState();
     412              : 
     413              :     // Other
     414              :     const Selection& selection() const;
     415              :     void select(EngravingItem* item, SelectType = SelectType::SINGLE, staff_idx_t staff = 0);
     416              :     void deselect(EngravingItem* el);
     417              : 
     418              : private:
     419              : 
     420     22288418 :     Score* score() override { return m_score; }
     421              : 
     422              :     Score* m_score = nullptr;
     423              : 
     424              :     LayoutConfiguration m_configuration;
     425              :     DomAccessor m_dom;
     426              :     LayoutState m_state;
     427              : };
     428              : }
        

Generated by: LCOV version 2.0-1