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 : #include "engravingitem.h"
26 :
27 : namespace mu::engraving {
28 : class Factory;
29 : class Measure;
30 : class Segment;
31 : class ChordRest;
32 : class Spanner;
33 : class System;
34 :
35 : //-------------------------------------------------------------------
36 : // SegmentType
37 : //
38 : // Type values determine the order of segments for a given tick
39 : //-------------------------------------------------------------------
40 :
41 : enum class SegmentType {
42 : ///.\{
43 : Invalid = 0x0,
44 : BeginBarLine = 0x1,
45 : HeaderClef = 0x2,
46 : KeySig = 0x4,
47 : Ambitus = 0x8,
48 : Breath = 0x10,
49 : TimeSig = 0x20,
50 : StartRepeatBarLine = 0x40,
51 : ClefStartRepeatAnnounce = 0x80,
52 : KeySigStartRepeatAnnounce = 0x100,
53 : TimeSigStartRepeatAnnounce = 0x200,
54 : Clef = 0x400,
55 : BarLine = 0x800,
56 : //--
57 : TimeTick = 0x1000,
58 : ChordRest = 0x2000,
59 : //--
60 : ClefRepeatAnnounce = 0x4000,
61 : KeySigRepeatAnnounce = 0x8000,
62 : TimeSigRepeatAnnounce = 0x10000,
63 : //--
64 : EndBarLine = 0x20000,
65 : KeySigAnnounce = 0x40000,
66 : TimeSigAnnounce = 0x80000,
67 : //--
68 : All = -1, ///< Includes all barline types
69 : /// Alias for `BeginBarLine | StartRepeatBarLine | BarLine | EndBarLine`
70 : BarLineTypes = BeginBarLine | StartRepeatBarLine | BarLine | EndBarLine,
71 : CourtesyTimeSigTypes = TimeSigAnnounce | TimeSigRepeatAnnounce | TimeSigStartRepeatAnnounce,
72 : CourtesyKeySigTypes = KeySigAnnounce | KeySigRepeatAnnounce | KeySigStartRepeatAnnounce,
73 : CourtesyClefTypes = ClefRepeatAnnounce | ClefStartRepeatAnnounce,
74 : TimeSigTypes = TimeSig | CourtesyTimeSigTypes,
75 : KeySigTypes = KeySig | CourtesyKeySigTypes,
76 : ClefTypes = Clef | HeaderClef | CourtesyClefTypes,
77 : // Only types with non-null duration
78 : Duration = TimeTick | ChordRest,
79 : ///\}
80 : };
81 :
82 1272073 : constexpr SegmentType operator|(const SegmentType t1, const SegmentType t2)
83 : {
84 1272073 : return static_cast<SegmentType>(static_cast<int>(t1) | static_cast<int>(t2));
85 : }
86 :
87 5744439 : constexpr bool operator&(const SegmentType t1, const SegmentType t2)
88 : {
89 5744439 : return static_cast<int>(t1) & static_cast<int>(t2);
90 : }
91 :
92 0 : constexpr SegmentType operator ~(const SegmentType& t)
93 : {
94 0 : return static_cast<SegmentType>(~static_cast<int>(t));
95 : }
96 :
97 : //------------------------------------------------------------------------
98 : // @@ Segment
99 : // A segment holds all vertical aligned staff elements.
100 : // Segments are typed and contain only Elements of the same type.
101 : //
102 : // All Elements in a segment start at the same tick. The Segment can store one EngravingItem for
103 : // each voice in each staff in the score.
104 : // Some elements (Clef, KeySig, TimeSig etc.) are assumed to always have voice zero
105 : // and can be found in _elist[staffIdx * VOICES];
106 :
107 : // Segments are children of Measures and store Clefs, KeySigs, TimeSigs,
108 : // BarLines and ChordRests.
109 : //
110 : // @P annotations array[EngravingItem] the list of annotations (read only)
111 : // @P next Segment the next segment in the whole score; null at last score segment (read-only)
112 : // @P nextInMeasure Segment the next segment in measure; null at last measure segment (read-only)
113 : // @P prev Segment the previous segment in the whole score; null at first score segment (read-only)
114 : // @P prevInMeasure Segment the previous segment in measure; null at first measure segment (read-only)
115 : // @P segmentType enum (Segment.All, .Ambitus, .BarLine, .Breath, .ChordRest, .Clef, .EndBarLine, .Invalid, .KeySig, .KeySigAnnounce, .StartRepeatBarLine, .TimeSig, .TimeSigAnnounce)
116 : // @P tick int midi tick position (read only)
117 : //------------------------------------------------------------------------
118 :
119 : class Segment final : public EngravingItem
120 : {
121 131841 : OBJECT_ALLOCATOR(engraving, Segment)
122 1316 : DECLARE_CLASSOF(ElementType::SEGMENT)
123 :
124 : protected:
125 : EngravingItem* getElement(staff_idx_t staff) const; //??
126 :
127 : public:
128 :
129 : ~Segment();
130 :
131 : void setOwnershipParent(DummyParentOr<Measure> parent);
132 :
133 0 : Segment* clone() const override { return new Segment(*this); }
134 :
135 : void setScore(Score*) override;
136 :
137 686985 : inline bool isActive() const { return !isTimeTickType() && enabled() && visible(); }
138 :
139 18694839 : Segment* next() const { return m_next; }
140 : Segment* next(SegmentType) const;
141 : Segment* nextActive() const;
142 : Segment* nextEnabled() const;
143 : Segment* nextInStaff(staff_idx_t staffIdx, SegmentType t = SegmentType::ChordRest) const;
144 136919 : void setNext(Segment* e) { m_next = e; }
145 :
146 4540394 : Segment* prev() const { return m_prev; }
147 : Segment* prev(SegmentType) const;
148 : Segment* prevWithElementsOnTrack(track_idx_t trackIdx, SegmentType segType = SegmentType::ChordRest) const;
149 : Segment* prevActive() const;
150 : Segment* prevEnabled() const;
151 120407 : void setPrev(Segment* e) { m_prev = e; }
152 :
153 : // don’t stop at measure boundary:
154 : Segment* next1() const;
155 : Segment* next1enabled() const;
156 : Segment* next1MM() const;
157 : Segment* next1MMenabled() const;
158 : Segment* next1(SegmentType) const;
159 : Segment* next1WithElemsOnStaff(staff_idx_t staffIdx, SegmentType segType = SegmentType::ChordRest) const;
160 : Segment* next1WithElemsOnTrack(track_idx_t trackIdx, SegmentType segType = SegmentType::ChordRest) const;
161 : Segment* next1MM(SegmentType) const;
162 :
163 : Segment* prev1() const;
164 : Segment* prev1WithElemsOnStaff(staff_idx_t staffIdx, SegmentType segType = SegmentType::ChordRest) const;
165 : Segment* prev1WithElemsOnTrack(track_idx_t trackIdx, SegmentType segType = SegmentType::ChordRest) const;
166 : Segment* prev1enabled() const;
167 : Segment* prev1MM() const;
168 : Segment* prev1MMenabled() const;
169 : Segment* prev1(SegmentType) const;
170 : Segment* prev1MM(SegmentType) const;
171 :
172 : Segment* nextCR(track_idx_t track = muse::nidx, bool sameStaff = false) const;
173 :
174 : ChordRest* nextChordRest(track_idx_t track, bool backwards = false, bool stopAtMeasureBoundary = false) const;
175 :
176 : EngravingItem* element(track_idx_t track) const;
177 :
178 2840690 : const std::vector<EngravingItem*>& elist() const { return m_elist; }
179 831480 : std::vector<EngravingItem*>& elist() { return m_elist; }
180 :
181 : void removeElement(track_idx_t track);
182 : void setElement(track_idx_t track, EngravingItem* el);
183 : void scanElements(std::function<void(EngravingItem*)> func) override;
184 :
185 15717397 : Measure* measure() const { return toMeasure(ownershipParent()); }
186 : System* system() const;
187 474208 : double x() const override { return ldata()->pos().x(); }
188 :
189 : void insertStaff(staff_idx_t staff);
190 : void removeStaff(staff_idx_t staff);
191 :
192 : void add(EngravingItem*) override;
193 : void remove(EngravingItem*) override;
194 : void swapElements(track_idx_t i1, track_idx_t i2);
195 :
196 : void sortStaves(std::vector<staff_idx_t>& dst);
197 : const char* subTypeName() const;
198 :
199 : static const char* subTypeName(SegmentType);
200 : static SegmentType segmentType(ElementType type);
201 :
202 7282686 : SegmentType segmentType() const { return m_segmentType; }
203 : void setSegmentType(SegmentType t);
204 :
205 6287 : bool empty() const { return flag(ElementFlag::EMPTY); }
206 38788 : bool written() const { return flag(ElementFlag::WRITTEN); }
207 73740 : void setWritten(bool val) const { setFlag(ElementFlag::WRITTEN, val); }
208 97075 : bool endOfMeasureChange() const { return flag(ElementFlag::END_OF_MEASURE_CHANGE); } // Key/time sigs which should be placed at the end of the measure
209 16 : void setEndOfMeasureChange(bool val) const { setFlag(ElementFlag::END_OF_MEASURE_CHANGE, val); }
210 :
211 : void fixStaffIdx();
212 :
213 64021 : double stretch() const { return m_stretch; }
214 171215 : void setStretch(double v) { m_stretch = v; }
215 :
216 6455217 : Fraction rtick() const override { return m_tick; }
217 21391 : void setRtick(const Fraction& v) { assert(v >= Fraction(0, 1)); m_tick = v; }
218 : Fraction tick() const override;
219 :
220 1099692 : Fraction ticks() const { return m_ticks; }
221 97209 : void setTicks(const Fraction& v) { m_ticks = v; }
222 :
223 : double widthInStaff(staff_idx_t staffIdx, SegmentType nextSegType = SegmentType::ChordRest) const;
224 : Fraction ticksInStaff(staff_idx_t staffIdx) const;
225 :
226 : bool splitsTuplet() const;
227 :
228 1046658 : const std::vector<EngravingItem*>& annotations() const { return m_annotations; }
229 : void clearAnnotations();
230 : void removeAnnotation(EngravingItem* e);
231 : bool hasAnnotationOrElement(ElementType type, track_idx_t minTrack, track_idx_t maxTrack) const;
232 : bool hasAnnotationOrElement(staff_idx_t staffIdx) const;
233 : EngravingItem* findAnnotation(ElementType type, track_idx_t minTrack, track_idx_t maxTrack) const;
234 : std::vector<EngravingItem*> findAnnotations(ElementType type, track_idx_t minTrack, track_idx_t maxTrack) const;
235 : bool hasElements() const;
236 : bool hasElements(track_idx_t minTrack, track_idx_t maxTrack) const;
237 : bool hasElements(staff_idx_t staffIdx) const;
238 : bool allElementsInvisible() const;
239 :
240 488312 : Spatium extraLeadingSpace() const { return m_extraLeadingSpace; }
241 0 : void setExtraLeadingSpace(Spatium v) { m_extraLeadingSpace = v; }
242 :
243 : PropertyValue getProperty(Pid propertyId) const override;
244 : bool setProperty(Pid propertyId, const PropertyValue&) override;
245 : PropertyValue propertyDefault(Pid) const override;
246 :
247 : bool operator<(const Segment&) const;
248 : bool operator>(const Segment&) const;
249 :
250 : String accessibleExtraInfo() const override;
251 :
252 : #ifndef ENGRAVING_NO_ACCESSIBILITY
253 : AccessibleItemPtr createAccessible() override;
254 : #endif
255 :
256 : EngravingItem* firstInNextSegments(staff_idx_t activeStaff) const; //<
257 : EngravingItem* lastInPrevSegments(staff_idx_t activeStaff) const; //<
258 : EngravingItem* firstElementForNavigation(staff_idx_t staff) const; //< These methods are used for navigation
259 : EngravingItem* lastElementForNavigation(staff_idx_t staff) const; //< for next-element and prev-element
260 : EngravingItem* firstElementOfSegment(staff_idx_t activeStaff) const;
261 : EngravingItem* nextElementOfSegment(EngravingItem* e, staff_idx_t activeStaff) const;
262 : EngravingItem* prevElementOfSegment(EngravingItem* e, staff_idx_t activeStaff) const;
263 : EngravingItem* lastElementOfSegment(staff_idx_t activeStaff) const;
264 : EngravingItem* nextAnnotation(EngravingItem* e) const;
265 : EngravingItem* prevAnnotation(EngravingItem* e) const;
266 : EngravingItem* firstAnnotation(staff_idx_t activeStaff) const;
267 : EngravingItem* lastAnnotation(staff_idx_t activeStaff) const;
268 : Spanner* firstSpanner(staff_idx_t activeStaff) const;
269 : Spanner* lastSpanner(staff_idx_t activeStaff) const;
270 : bool notChordRestType() const;
271 : using EngravingItem::nextElement;
272 : EngravingItem* nextElement(staff_idx_t activeStaff);
273 : using EngravingItem::prevElement;
274 : EngravingItem* prevElement(staff_idx_t activeStaff);
275 :
276 : EngravingItem* firstElement(staff_idx_t staffIdx) const;
277 :
278 360099 : std::vector<Shape> shapes() { return m_shapes; }
279 1776906 : const std::vector<Shape>& shapes() const { return m_shapes; }
280 3211820 : const Shape& staffShape(staff_idx_t staffIdx) const { return m_shapes[staffIdx]; }
281 40149 : Shape& staffShape(staff_idx_t staffIdx) { return m_shapes[staffIdx]; }
282 : void createShapes();
283 : void createShape(staff_idx_t staffIdx);
284 : double minRight() const;
285 : double minLeft() const;
286 :
287 125340 : double widthOffset() const { return m_widthOffset; }
288 287865 : void clearWidthOffset() { m_widthOffset = 0.0; }
289 1762 : void addWidthOffset(double w) { m_widthOffset += w; }
290 : void setWidthOffset(double w) { m_widthOffset = w; }
291 :
292 : double elementsTopOffsetFromSkyline(staff_idx_t staffIndex) const;
293 : double elementsBottomOffsetFromSkyline(staff_idx_t staffIndex) const;
294 :
295 : //! spacing is additional width of segment, for example accidental needs this spacing to avoid overlapping
296 : void setSpacing(double);
297 : double spacing() const;
298 :
299 : // some helper function
300 6108387 : ChordRest* cr(track_idx_t track) const { return toChordRest(m_elist[track]); }
301 6027989 : bool isType(const SegmentType t) const { return int(m_segmentType) & int(t); }
302 1509598 : bool isJustType(const SegmentType t) const { return m_segmentType == t; }
303 883 : bool isBeginBarLineType() const { return m_segmentType == SegmentType::BeginBarLine; }
304 1331100 : bool isClefType() const { return m_segmentType == SegmentType::Clef; }
305 737053 : bool isHeaderClefType() const { return m_segmentType == SegmentType::HeaderClef; }
306 571426 : bool isKeySigType() const { return m_segmentType == SegmentType::KeySig; }
307 : bool isAmbitusType() const { return m_segmentType == SegmentType::Ambitus; }
308 642946 : bool isTimeSigType() const { return m_segmentType == SegmentType::TimeSig; }
309 : bool hasTimeSigAboveStaves() const;
310 : bool makeSpaceForTimeSigAboveStaves() const;
311 : bool hasTimeSigAcrossStaves() const;
312 1070774 : bool isStartRepeatBarLineType() const { return m_segmentType == SegmentType::StartRepeatBarLine; }
313 9 : bool isBarLineType() const { return m_segmentType == SegmentType::BarLine; }
314 866136 : bool isBreathType() const { return m_segmentType == SegmentType::Breath; }
315 16366832 : bool isChordRestType() const { return m_segmentType == SegmentType::ChordRest; }
316 33647 : bool isClefRepeatAnnounceType() const { return m_segmentType == SegmentType::ClefRepeatAnnounce; }
317 31723 : bool isKeySigRepeatAnnounceType() const { return m_segmentType == SegmentType::KeySigRepeatAnnounce; }
318 31698 : bool isTimeSigRepeatAnnounceType() const { return m_segmentType == SegmentType::TimeSigRepeatAnnounce; }
319 460258 : bool isEndBarLineType() const { return m_segmentType == SegmentType::EndBarLine; }
320 10257 : bool isKeySigAnnounceType() const { return m_segmentType == SegmentType::KeySigAnnounce; }
321 10465 : bool isTimeSigAnnounceType() const { return m_segmentType == SegmentType::TimeSigAnnounce; }
322 10511 : bool isCourtesySegment() const
323 : {
324 10511 : return m_segmentType & (SegmentType::CourtesyTimeSigTypes | SegmentType::CourtesyKeySigTypes | SegmentType::CourtesyClefTypes);
325 : }
326 :
327 979917 : bool isTimeTickType() const { return m_segmentType == SegmentType::TimeTick; }
328 757554 : bool isRightAligned() const { return isClefType() || isBreathType(); }
329 341064 : bool isMMRestSegment() const { return isChordRestType() && m_elist.front() && m_elist.front()->isMMRest(); }
330 :
331 : bool canWriteSpannerStartEnd(track_idx_t track, const Spanner* spanner) const;
332 :
333 : Fraction shortestChordRest() const;
334 :
335 : bool hasAccidentals() const;
336 :
337 3121540 : EngravingItem* preAppendedItem(track_idx_t track) { return m_preAppendedItems[track]; }
338 1028 : void preAppend(EngravingItem* item, track_idx_t track) { m_preAppendedItems[track] = item; }
339 531 : void clearPreAppended(track_idx_t track) { m_preAppendedItems[track] = nullptr; }
340 :
341 : bool goesBefore(const Segment* nextSegment) const;
342 :
343 : void checkEmpty() const;
344 :
345 : double xPosInSystemCoords() const;
346 : void setXPosInSystemCoords(double x);
347 :
348 : bool isTupletSubdivisionOnStaff(staff_idx_t staffIdx) const;
349 : bool isInsideTupletOnStaff(staff_idx_t staffIdx) const;
350 :
351 : private:
352 :
353 : void addArticulationsToShape(const Chord* chord, Shape& shape);
354 :
355 : friend class Factory;
356 : Segment(DummyParentOr<Measure> m);
357 : Segment(DummyParentOr<Measure>, SegmentType, const Fraction&);
358 : Segment(const Segment&);
359 :
360 : void init();
361 : void checkElement(EngravingItem*, track_idx_t track);
362 110823 : void setEmpty(bool val) const { setFlag(ElementFlag::EMPTY, val); }
363 :
364 : SegmentType m_segmentType = SegmentType::Invalid;
365 : Fraction m_tick; // { Fraction(0, 1) };
366 : Fraction m_ticks; // { Fraction(0, 1) };
367 : Spatium m_extraLeadingSpace;
368 : double m_stretch = 1.0;
369 : double m_widthOffset = 0.0; // part of the segment width that will not be stretched during system justification
370 :
371 : Segment* m_next = nullptr; // linked list of segments inside a measure
372 : Segment* m_prev = nullptr;
373 :
374 : std::vector<EngravingItem*> m_annotations;
375 : std::vector<EngravingItem*> m_elist; // EngravingItem storage, size = staves * VOICES.
376 : std::vector<EngravingItem*> m_preAppendedItems; // Container for items appended to the left of this segment (example: grace notes), size = staves * VOICES.
377 : std::vector<Shape> m_shapes; // size = staves
378 : double m_spacing = 0;
379 : };
380 : } // namespace mu::engraving
381 :
382 : #ifndef NO_QT_SUPPORT
383 16 : Q_DECLARE_METATYPE(mu::engraving::SegmentType)
384 : #endif
|