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 : #pragma once
24 :
25 : /**
26 : \file
27 : Definition of class Measure.
28 : */
29 :
30 : #include "measurebase.h"
31 :
32 : #include "segmentlist.h"
33 :
34 : namespace mu::engraving::read400 {
35 : class MeasureRead;
36 : }
37 :
38 : namespace mu::engraving::read410 {
39 : class MeasureRead;
40 : }
41 :
42 : namespace mu::engraving::read460 {
43 : class MeasureRead;
44 : }
45 :
46 : namespace mu::engraving::read500 {
47 : class MeasureRead;
48 : }
49 :
50 : namespace mu::engraving::write {
51 : class MeasureWrite;
52 : }
53 :
54 : namespace mu::engraving {
55 : class AccidentalState;
56 : class Chord;
57 : class ChordRest;
58 : class MMRestRange;
59 : class MeasureNumber;
60 : class MeasureRepeat;
61 : class Note;
62 : class Part;
63 : class Score;
64 : class Spacer;
65 : class Staff;
66 : class System;
67 : class TieMap;
68 : class Transaction;
69 :
70 : //---------------------------------------------------------
71 : // MeasureNumberMode
72 : //---------------------------------------------------------
73 :
74 : enum class MeasureNumberMode : char {
75 : AUTO, // show measure number depending on style
76 : SHOW, // always show measure number
77 : HIDE // don’t show measure number
78 : };
79 :
80 : //---------------------------------------------------------
81 : // MStaff
82 : /// Per staff values of measure.
83 : //---------------------------------------------------------
84 :
85 : class MStaff
86 : {
87 : public:
88 24600 : MStaff() {}
89 : ~MStaff();
90 : MStaff(const MStaff&);
91 :
92 : void setScore(Score*);
93 : void setTrack(track_idx_t);
94 :
95 33524 : MeasureNumber* measureNumber() const { return m_measureNumber; }
96 2336 : void setMeasureNumber(MeasureNumber* t) { m_measureNumber = t; }
97 :
98 112904 : MMRestRange* mmRangeText() const { return m_mmRangeText; }
99 0 : void setMMRangeText(MMRestRange* r) { m_mmRangeText = r; }
100 :
101 604842 : StaffLines* lines() const { return m_lines; }
102 24600 : void setLines(StaffLines* l) { m_lines = l; }
103 :
104 156310 : Spacer* vspacerUp() const { return m_vspacerUp; }
105 0 : void setVspacerUp(Spacer* s) { m_vspacerUp = s; }
106 164168 : Spacer* vspacerDown() const { return m_vspacerDown; }
107 1 : void setVspacerDown(Spacer* s) { m_vspacerDown = s; }
108 :
109 223137 : bool hasVoices() const { return m_hasVoices; }
110 9439 : void setHasVoices(bool val) { m_hasVoices = val; }
111 :
112 157660 : bool visible() const { return m_visible; }
113 21 : void setVisible(bool val) { m_visible = val; }
114 :
115 2684879 : bool stemless() const { return m_stemless; }
116 847 : void setStemless(bool val) { m_stemless = val; }
117 :
118 39096 : AutoOnOff hideIfEmpty() const { return m_hideIfEmpty; }
119 0 : void setHideIfEmpty(AutoOnOff val) { m_hideIfEmpty = val; }
120 :
121 0 : bool corrupted() const { return m_corrupted; }
122 1201 : void setCorrupted(bool val) { m_corrupted = val; }
123 :
124 403071 : int measureRepeatCount() const { return m_measureRepeatCount; }
125 4563 : void setMeasureRepeatCount(int n) { m_measureRepeatCount = n; }
126 :
127 : private:
128 : MeasureNumber* m_measureNumber = nullptr; // Measure number text object
129 : MMRestRange* m_mmRangeText = nullptr; // Multi measure rest range text object
130 : StaffLines* m_lines = nullptr;
131 : Spacer* m_vspacerUp = nullptr;
132 : Spacer* m_vspacerDown = nullptr;
133 : bool m_hasVoices = false; // indicates that MStaff contains more than one voice,
134 : // this changes some layout rules
135 :
136 : bool m_visible = true;
137 : bool m_stemless = false;
138 : AutoOnOff m_hideIfEmpty = AutoOnOff::AUTO; // whether this MStaff wants its staff to be hidden on its system
139 : // when the staff is empty on that system
140 :
141 : bool m_corrupted = false;
142 : int m_measureRepeatCount = 0;
143 : };
144 :
145 : //---------------------------------------------------------
146 : // @@ Measure
147 : /// one measure in a system
148 : //
149 : // @P firstSegment Segment the first segment of the measure (read-only)
150 : // @P lastSegment Segment the last segment of the measure (read-only)
151 : //---------------------------------------------------------
152 :
153 : class Measure final : public MeasureBase
154 : {
155 33175 : OBJECT_ALLOCATOR(engraving, Measure)
156 20360 : DECLARE_CLASSOF(ElementType::MEASURE)
157 :
158 : public:
159 :
160 : ~Measure();
161 :
162 0 : Measure* clone() const override { return new Measure(*this); }
163 : void setScore(Score* s) override;
164 : Measure* cloneMeasure(Score*, const Fraction& tick, TieMap*);
165 :
166 0 : bool isEditable() const override { return false; }
167 : void checkMeasure(staff_idx_t idx, bool useGapRests = true);
168 :
169 : void add(EngravingItem*) override;
170 : void remove(EngravingItem*) override;
171 : void change(EngravingItem* o, EngravingItem* n) override;
172 : void spatiumChanged(double oldValue, double newValue) override;
173 :
174 : bool hasVoices(staff_idx_t staffIdx, Fraction stick, Fraction len, bool considerInvisible = false) const;
175 : bool hasVoices(staff_idx_t staffIdx) const;
176 : void setHasVoices(staff_idx_t staffIdx, bool v);
177 :
178 : StaffLines* staffLines(staff_idx_t staffIdx) const;
179 : Spacer* vspacerDown(staff_idx_t staffIdx) const;
180 : Spacer* vspacerUp(staff_idx_t staffIdx) const;
181 : void setStaffVisible(staff_idx_t staffIdx, bool visible);
182 : void setStaffStemless(staff_idx_t staffIdx, bool stemless);
183 : AutoOnOff hideStaffIfEmpty(staff_idx_t staffIdx) const;
184 : void setHideStaffIfEmpty(staff_idx_t staffIdx, AutoOnOff hideIfEmpty);
185 0 : bool corrupted(staff_idx_t staffIdx) const { return m_mstaves[staffIdx]->corrupted(); }
186 1201 : void setCorrupted(staff_idx_t staffIdx, bool val) { m_mstaves[staffIdx]->setCorrupted(val); }
187 8110 : MeasureNumber* measureNumber(staff_idx_t staffIdx) const { return m_mstaves[staffIdx]->measureNumber(); }
188 0 : void setMeasureNumber(staff_idx_t staffIdx, MeasureNumber* t) { m_mstaves[staffIdx]->setMeasureNumber(t); }
189 :
190 428575 : const std::vector<MStaff*>& mstaves() const { return m_mstaves; }
191 236481 : std::vector<MStaff*>& mstaves() { return m_mstaves; }
192 :
193 : void setMMRangeText(staff_idx_t staffIdx, MMRestRange*);
194 : MMRestRange* mmRangeText(staff_idx_t staffIdx) const;
195 :
196 : void createStaves(staff_idx_t);
197 :
198 231622 : Fraction timesig() const { return m_timesig; }
199 19835 : void setTimesig(const Fraction& f) { m_timesig = f; }
200 :
201 : Fraction stretchedLen(const Staff*) const;
202 1792 : bool isIrregular() const { return m_timesig != m_len; }
203 :
204 34938 : int measureNumber() const { return m_measureNumber; }
205 34223 : void setMeasureNumber(int n) { m_measureNumber = n; }
206 46991 : int measureNumberOffset() const { return m_measureNumberOffset; }
207 3604 : void setMeasureNumberOffset(int n) { m_measureNumberOffset = n; }
208 :
209 497828 : bool excludeFromNumbering() const { return flag(ElementFlag::EXCLUDE_FROM_NUMBERING); }
210 18450 : void setExcludeFromNumbering(bool v) { setFlag(ElementFlag::EXCLUDE_FROM_NUMBERING, v); }
211 :
212 11954 : MeasureNumberMode measureNumberMode() const { return m_measureNumberMode; }
213 0 : void setMeasureNumberMode(MeasureNumberMode v) { m_measureNumberMode = v; }
214 :
215 296254 : bool repeatEnd() const { return flag(ElementFlag::REPEAT_END); }
216 4378 : void setRepeatEnd(bool v) { setFlag(ElementFlag::REPEAT_END, v); }
217 :
218 163115 : bool repeatStart() const { return flag(ElementFlag::REPEAT_START); }
219 4686 : void setRepeatStart(bool v) { setFlag(ElementFlag::REPEAT_START, v); }
220 :
221 178077 : bool repeatJump() const { return flag(ElementFlag::REPEAT_JUMP); }
222 1344 : void setRepeatJump(bool v) { setFlag(ElementFlag::REPEAT_JUMP, v); }
223 :
224 99038 : bool hasCourtesyKeySig() const { return flag(ElementFlag::COURTESY_KEYSIG); }
225 118269 : void setHasCourtesyKeySig(bool v) { setFlag(ElementFlag::COURTESY_KEYSIG, v); }
226 :
227 29300 : bool hasCourtesyTimeSig() const { return flag(ElementFlag::COURTESY_TIMESIG); }
228 55263 : void setHasCourtesyTimeSig(bool v) const { setFlag(ElementFlag::COURTESY_TIMESIG, v); }
229 :
230 1197 : bool hasCourtesyClef() const { return flag(ElementFlag::COURTESY_CLEF); }
231 54773 : void setHasCourtesyClef(bool v) const { setFlag(ElementFlag::COURTESY_CLEF, v); }
232 :
233 : bool endOfMeasureChange() const { return flag(ElementFlag::END_OF_MEASURE_CHANGE); }
234 26618 : void setEndOfMeasureChange(bool val) const { setFlag(ElementFlag::END_OF_MEASURE_CHANGE, val); }
235 :
236 2571858 : Segment* first() const { return m_segments.first(); }
237 823389 : Segment* first(SegmentType t) const { return m_segments.first(t); }
238 131313 : Segment* firstEnabled() const { return m_segments.first(ElementFlag::ENABLED); }
239 30515 : Segment* firstActive() const { return m_segments.firstActive(); }
240 :
241 1603820 : Segment* last() const { return m_segments.last(); }
242 1136 : Segment* last(SegmentType t) const { return m_segments.last(t); }
243 4893 : Segment* lastEnabled() const { return m_segments.last(ElementFlag::ENABLED); }
244 1182752 : SegmentList& segments() { return m_segments; }
245 239281 : const SegmentList& segments() const { return m_segments; }
246 :
247 : double userStretch() const;
248 2 : void setUserStretch(double v) { m_userStretch = v; }
249 :
250 : void computeTicks();
251 : Fraction anacrusisOffset() const;
252 : Fraction maxTicks() const;
253 :
254 : bool showMeasureNumber() const;
255 : bool showMeasureNumberInAutoMode() const;
256 : bool showMeasureNumberOnStaff(staff_idx_t staffIdx) const;
257 :
258 : Chord* findChord(Fraction tick, track_idx_t track) const;
259 : ChordRest* findChordRest(Fraction tick, track_idx_t track) const;
260 : Fraction snap(const Fraction& tick, const PointF p) const;
261 : Fraction snapNote(const Fraction& tick, const PointF p, int staff) const;
262 :
263 : Segment* searchSegment(double x, SegmentType st, track_idx_t strack, track_idx_t etrack, const Segment* preferredSegment = nullptr,
264 : double spacingFactor = 0.5) const;
265 :
266 : void insertStaff(Staff*, staff_idx_t staff);
267 : void insertMStaff(MStaff* staff, staff_idx_t idx);
268 : void removeMStaff(MStaff* staff, staff_idx_t idx);
269 :
270 : void moveTicks(const Fraction& diff) override;
271 :
272 : void cmdRemoveStaves(staff_idx_t s, staff_idx_t e);
273 : void cmdAddStaves(staff_idx_t s, staff_idx_t e, bool createRest);
274 : void removeStaves(staff_idx_t s, staff_idx_t e);
275 : void insertStaves(staff_idx_t s, staff_idx_t e);
276 :
277 : double tick2pos(Fraction) const;
278 : Segment* tick2segment(const Fraction& tick, SegmentType st = SegmentType::ChordRest);
279 :
280 : void sortStaves(std::vector<staff_idx_t>& dst);
281 :
282 : bool acceptDrop(EditData&) const override;
283 : EngravingItem* drop(Transaction& tx, EditData&) override;
284 :
285 2171 : int repeatCount() const { return m_repeatCount; }
286 1494 : void setRepeatCount(int val) { m_repeatCount = val; }
287 :
288 : Segment* findSegmentR(SegmentType st, const Fraction&) const;
289 : Segment* undoGetSegmentR(SegmentType st, const Fraction& f);
290 : Segment* getSegmentR(SegmentType st, const Fraction& f);
291 : Segment* findFirstR(SegmentType st, const Fraction& rtick) const;
292 :
293 : // segment routines with absolute tick values
294 65444 : Segment* findSegment(SegmentType st, const Fraction& f) const { return findSegmentR(st, f - tick()); }
295 7127 : Segment* undoGetSegment(SegmentType st, const Fraction& f) { return undoGetSegmentR(st, f - tick()); }
296 57130 : Segment* getSegment(SegmentType st, const Fraction& f) { return getSegmentR(st, f - tick()); }
297 : Segment* undoGetChordRestOrTimeTickSegment(const Fraction& f);
298 : Segment* getChordRestOrTimeTickSegment(const Fraction& f);
299 :
300 : void connectTremolo();
301 :
302 : void setEndBarLineType(BarLineType val, track_idx_t track, bool visible = true, Color color = Color());
303 :
304 : void scanElements(std::function<void(EngravingItem*)> func) override;
305 : void createVoice(int track);
306 : void adjustToLen(Fraction, bool appendRestsIfNecessary = true);
307 :
308 : AccidentalVal findAccidental(const Note*) const;
309 : AccidentalVal findAccidental(const Segment* s, staff_idx_t staffIdx, int line, bool& error) const;
310 : void checkMultiVoices(staff_idx_t staffIdx);
311 : bool hasVoice(track_idx_t track) const;
312 : bool isEmpty(staff_idx_t staffIdx) const;
313 : bool isCutawayClef(staff_idx_t staffIdx) const;
314 : bool isFullMeasureRest() const;
315 : bool visible(staff_idx_t staffIdx) const;
316 : bool stemless(staff_idx_t staffIdx) const;
317 : bool isFinalMeasureOfSection() const;
318 : LayoutBreak* sectionBreakElement(bool includeNextFrames = true) const;
319 : bool isAnacrusis() const;
320 : bool isFirstInSystem() const;
321 : bool isLastInSystem() const;
322 : bool isFirstInSection() const;
323 :
324 13340 : bool breakMultiMeasureRest() const { return m_breakMultiMeasureRest; }
325 910 : void setBreakMultiMeasureRest(bool val) { m_breakMultiMeasureRest = val; }
326 :
327 : bool empty() const;
328 : bool isOnlyRests(track_idx_t track) const;
329 : bool isOnlyGapRests(track_idx_t track) const;
330 :
331 0 : int playbackCount() const { return m_playbackCount; }
332 0 : void setPlaybackCount(int val) { m_playbackCount = val; }
333 : RectF staffPageBoundingRect(staff_idx_t staffIdx) const;
334 :
335 : PropertyValue getProperty(Pid propertyId) const override;
336 : bool setProperty(Pid propertyId, const PropertyValue&) override;
337 : PropertyValue propertyDefault(Pid) const override;
338 :
339 : void undoChangeProperty(Pid id, const PropertyValue& newValue);
340 : void undoChangeProperty(Pid id, const PropertyValue& newValue, PropertyFlags ps) override;
341 :
342 18491 : bool hasMMRest() const { return m_mmRest != nullptr; }
343 1035381 : bool isMMRest() const { return m_mmRestCount > 0; }
344 136059 : Measure* mmRest() const { return m_mmRest; }
345 : Measure* coveringMMRestOrThis();
346 : const Measure* coveringMMRestOrThis() const;
347 101 : void setMMRest(Measure* m) { m_mmRest = m; }
348 17225 : int mmRestCount() const { return m_mmRestCount; } // number of measures m_mmRest spans
349 681 : void setMMRestCount(int n) { m_mmRestCount = n; }
350 : Measure* mmRestFirst() const;
351 : Measure* mmRestLast() const;
352 :
353 : int measureRepeatCount(staff_idx_t staffIdx) const;
354 : bool containsMeasureRepeat(const staff_idx_t staffIdxFrom, const staff_idx_t staffIdxTo) const;
355 : void setMeasureRepeatCount(int n, staff_idx_t staffIdx);
356 : bool isMeasureRepeatGroup(staff_idx_t staffIdx) const;
357 : bool isMeasureRepeatGroupWithNextM(staff_idx_t staffIdx) const;
358 : bool isMeasureRepeatGroupWithPrevM(staff_idx_t staffIdx) const;
359 : Measure* firstOfMeasureRepeatGroup(staff_idx_t staffIdx) const; // used to find beginning of group
360 : MeasureRepeat* measureRepeatElement(staff_idx_t staffIdx) const; // get measure repeat element from anywhere within group
361 : int measureRepeatNumMeasures(staff_idx_t staffIdx) const;
362 : bool isOneMeasureRepeat(staff_idx_t staffIdx) const;
363 : bool nextIsOneMeasureRepeat(staff_idx_t staffidx) const;
364 : bool prevIsOneMeasureRepeat(staff_idx_t staffIdx) const;
365 :
366 : ChordRest* lastChordRest(track_idx_t track) const;
367 : ChordRest* firstChordRest(track_idx_t track) const;
368 :
369 : EngravingItem* nextElementStaff(staff_idx_t staff, EngravingItem* fromItem = nullptr);
370 : EngravingItem* prevElementStaff(staff_idx_t staff, EngravingItem* fromItem = nullptr);
371 :
372 : double firstNoteRestSegmentX(bool leading = false) const;
373 : double endingXForOpenEndedLines() const;
374 :
375 : String accessibleInfo() const override;
376 :
377 : void styleChanged() override;
378 :
379 : #ifndef ENGRAVING_NO_ACCESSIBILITY
380 : AccessibleItemPtr createAccessible() override;
381 : #endif
382 :
383 : const BarLine* endBarLine() const;
384 : const BarLine* endBarLine(staff_idx_t staffIdx, bool first = false) const;
385 : BarLineType endBarLineType() const;
386 : bool endBarLineVisible() const;
387 : const BarLine* startBarLine() const;
388 : const BarLine* startBarLine(staff_idx_t staffIdx, bool first = false) const;
389 : void triggerLayout() const override;
390 : void triggerLayout(staff_idx_t staffIdx) const;
391 :
392 : void checkHeader();
393 : void checkTrailer();
394 : void checkEndOfMeasureChange();
395 :
396 : void respaceSegments();
397 :
398 : bool canAddStringTunings(staff_idx_t staffIdx) const;
399 : bool canAddStaffTypeChange(staff_idx_t staffIdx) const;
400 :
401 : struct LayoutData : public MeasureBase::LayoutData {
402 : private:
403 : bool m_needLayout = true;
404 : public:
405 32036 : bool needLayout() const { return m_needLayout; }
406 60875 : void setNeedLayout(bool v) { m_needLayout = v; }
407 : };
408 300846 : DECLARE_LAYOUTDATA_METHODS(Measure)
409 :
410 : private:
411 :
412 : friend class Factory;
413 :
414 : Measure(Score* parent);
415 : Measure(const Measure&);
416 :
417 : void push_back(Segment* e);
418 : void push_front(Segment* e);
419 :
420 : void fillGap(const Fraction& pos, const Fraction& len, track_idx_t track, const Fraction& stretch, bool useGapRests = true);
421 :
422 : MStaff* mstaff(staff_idx_t staffIndex) const;
423 :
424 : std::vector<MStaff*> m_mstaves;
425 : SegmentList m_segments;
426 : Measure* m_mmRest = nullptr; // multi measure rest which replaces a measure range
427 :
428 : double m_userStretch = 0.0;
429 :
430 : Fraction m_timesig;
431 :
432 : int m_mmRestCount = 0; // number of measures an mmrest spans
433 :
434 : int m_playbackCount = 0; // temp. value used in RepeatList
435 : // counts how many times this measure was already played
436 :
437 : int m_repeatCount = 0; // end repeat marker and repeat count
438 :
439 : int m_measureNumber = 0; // counting from zero
440 : int m_measureNumberOffset = 0;
441 : MeasureNumberMode m_measureNumberMode = MeasureNumberMode::AUTO;
442 : bool m_breakMultiMeasureRest = false;
443 : };
444 : } // namespace mu::engraving
|