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 : }
|